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