首页 > 其他 > 详细

[Luogu] 宝藏

时间:2018-05-03 17:55:52      阅读:193      评论:0      收藏:0      [点我收藏+]

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

 

[Luogu] 宝藏

原文:https://www.cnblogs.com/shandongs1/p/8986417.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!