[Luogu] 宝藏

https://www.luogu.org/problemnew/show/P3959

模拟退火解法

发现prim求最小生成树是明显错误的

因为prim每次要取出边权最小的点

然而在这道T中这样做不一定是最优的

因此可以随机取出点,这就可能是最优

当重复次数达到一定次数时,就极有可能成为最优解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;
const int N = 20;
const int oo = 1e8;

int n, m;
int dis[N][N], deep[N];
struct Node {int u, v;};
Node have_used[N * 100];
bool vis[N];

bool operator < (const Node a, const Node b) {
    return deep[a.u] * dis[a.u][a.v] > deep[b.u] * dis[b.u][b.v];
}
priority_queue <Node> Q;

#define gc getchar()

inline int read() {
    int x = 0; char c = gc;
    while(c < '0' || c > '9') c = gc;
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x;
}

inline int Work(int S) {
    for(int i = 1; i <= n; i ++) deep[i] = 0, vis[i] = 0;
    int last(0), ret(0);
    while(!Q.empty()) Q.pop();
    Node E; deep[S] = 1; vis[S] = 1;
    for(int i = 1; i <= n; i ++) if(dis[S][i] != oo) {E.u = S, E.v = i; Q.push(E);}
    int T = n - 1;
    for(; T; T --) {
        E = Q.top(); Q.pop();
        while(!Q.empty() && (vis[E.v] || rand() % n == 0)) {
            if(!vis[E.v]) have_used[++ last] = E;
            E = Q.top(); Q.pop();
        }
        vis[E.v] = 1;
        deep[E.v] = deep[E.u] + 1;
        for(; last; last --) Q.push(have_used[last]);
        last = 0;
        ret += deep[E.u] * dis[E.u][E.v];
        Node E2;
        for(int i = 1; i <= n; i ++) {
            if((dis[E.v][i] != oo) && !vis[i]) {E2.v = i; E2.u = E.v;Q.push(E2);}
        }
    }
    return ret;
}

int main() {
    srand(20001206);
    n = read(); m = read();
    for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) dis[i][j] = oo;
    for(int i = 1; i <= m; i ++) {
        int a = read(), b = read(), c = read();
        dis[a][b] = dis[b][a] = min(dis[a][b], c); 
    }
    int Answer = oo, T = 1000;
    for(; T; T --) 
        for(int i = 1; i <= n; i ++) Answer = min(Answer, Work(i));
    cout << Answer; 
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/shandongs1/p/8986417.html
今日推荐