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;
}