[Luogu] Treasure

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

Simulated Annealing Solution

It is found that prim's minimum spanning tree is obviously wrong

Because prim has to take out the point with the smallest edge weight each time

However, doing so in this T is not necessarily optimal

So points can be picked randomly, which is probably optimal

When the number of repetitions reaches a certain number, it is very likely to become the optimal solution

#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();
        }
        force[Ev] = 1 ;
        deep[E.v] = deep[E.u] + 1;
        for(; last; last --) Q.push(have_used[last]);
        last = 0;
        ret += deep[I] * dis[I][Ev];
        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;
}

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325256607&siteId=291194637