宝藏
70分.......
我们发现 8!非常的小,带上一大串常数都没问题
因此我们考虑深搜
如何爆搜?
第一反应是枚举全排列然后去更新答案。
但是有问题啊,知道点开拓的顺序并没有什么用,我们还要知道它是由哪个点开拓而来的。
因此我们再枚举去开拓的点:
#include <cstdio> using namespace std; int a[55], l[55]; int cost[55][55]; int ans = 2147483645, tmp, n, m; #define getchar() (S==T&&(T=(S=BB)+fread(BB,1,1<<15,stdin),S==T)?EOF:*S++) char BB[1 << 16], *S = BB, *T = BB; inline int read () { int X = 0; char ch = 0; while(ch < 0 || ch > 9) ch = getchar(); while(ch >= 0 && ch <= 9) X = X * 10 + ch - '0', ch = getchar(); return X; } inline int min(int a, int b) { int c = (a - b) >> 31; return a ^ c | b ^ ~c; } inline void dfs(int e, int num) { if(num == n) { ans = min(tmp, ans); return; } if(tmp >= ans) return; for(int i = 1; i <= n; i ++) { if(l[i]) continue; for(int j = 1; j <= n; j ++) { if(cost[j][i] == 2147483645 || !l[j] || i == j) continue; tmp += l[j] * cost[j][i]; l[i] = l[j] + 1; dfs(i, num + 1); tmp -= l[j] * cost[j][i]; l[i] = 0; } } } int main() { int u, v; n = read(); m = read(); for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) cost[i][j] = 2147483645; for(int i = 1; i <= m; i ++) u = read(), v = read(), cost[u][v] = cost[v][u] = min(cost[u][v], read()); for(int i = 1; i <= n; i ++) { l[i] = 1; dfs(i, 1); l[i] = 0; } printf("%lld\n", ...); return 0; }