日本旅游签证时间,sd5000,黄家驹北京演唱会
题面好长啊。。。自己看吧。。
自己想了一个退火的思路,没想到第一次交85,多退了几次就a了哈哈哈
首先把没用的边去掉,然后剩下的边从小到大排序
这样我们就得到了一个选边的序列,我们要求答案强制按照这个序列选
每次退火的时候选两个点交换。
枚举每个点,判断是否能更新答案,
时间复杂度$o(200 * 1000 * n * m)$
/* */ #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<ctime> #include<cstring> #include<algorithm> #include<vector> #define pair pair<int, int> #define mp(x, y) make_pair(x, y) #define fi first #define se second using namespace std; const int maxn = 1001; const double eps = 1e-10, dlt = 0.97, inf = 1e9 + 7; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n, m; struct edge { int u, v, w; bool operator < (const edge &rhs) const { return w < rhs.w; } }e[maxn]; int link[maxn][maxn], num, fa[maxn]; void unionn(int x, int y) { fa[x] = y; } int find(int x) { if(fa[x] == x) return fa[x]; else return fa[x] = find(fa[x]); } vector<pair> v[maxn]; int dfs(int x, int cnt, int fa) { int ans = 0; for(int i = 0; i < v[x].size(); i++) { int to = v[x][i].fi, w = v[x][i].se; if(to != fa) ans += dfs(to, cnt + 1, x) + w * cnt; } return ans; } int solve() { int cur = inf, tot = 0, base = 0; for(int i = 1; i <= n; i++) fa[i] = i, v[i].clear(); for(int i = 1; i <= m; i++) { int x = e[i].u, y = e[i].v; int fx = find(x), fy = find(y); if(fx == fy) continue; tot++; unionn(fx, fy); v[x].push_back(mp(y, e[i].w)); v[y].push_back(mp(x, e[i].w)); } if(tot != n - 1) return inf; for(int i = 1; i <= n; i++) cur = min(cur, dfs(i, 1, 0)); return cur; } int main() { // freopen("testdata.in", "r", stdin); srand((unsigned)time(null)); memset(link, 0x7f, sizeof(link)); n = read(); m = read(); if(n == 1) { puts("0"); return 0; } for(int i = 1; i <= m; i++) { int x = read(), y = read(), w = read(); link[x][y] = min(link[x][y], w); link[y][x] = min(link[y][x], w); } for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++) if(link[i][j] <= inf) e[++num] = (edge) {i, j, link[i][j]}; sort(e + 1, e + num + 1); int ans = solve(); int times = 200; while(times--) { int now = inf; for(double t = 100000; t > eps; t *= dlt) { int x = rand() % num + 1, y = rand() % num + 1; //check(x, y); swap(e[x], e[y]); int nxt = solve(); if(nxt < ans) {ans = nxt; continue;} if(nxt < now || ((exp(now - nxt / t) < rand() / rand_max))) {now = nxt; continue;} swap(e[x], e[y]); } } printf("%d", ans); return 0; } /* 4 0 0 0 5000 2354 10000 8787 0 */
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
如何在没有core文件的情况下用dmesg+addr2line定位段错误
用QT制作3D点云显示器——QtDataVisualization
网友评论