宝藏

题面

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

  

posted @ 2019-08-20 13:46  [jackeylove]  阅读(132)  评论(0编辑  收藏  举报