码迷,mamicode.com
首页 > 其他好文 > 详细

luogu P3959 宝藏

时间:2018-09-13 22:43:18      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:fine   ons   ||   lse   dom   math   max   oid   exp   

题目链接

luogu P3959 宝藏

题解

开始写了个random_shuffle竟然水了70,然后退火一下就A了?
每次做生成树的时候,随机两条边的顺序交换
退火一下,就A了

代码

#include<cmath> 
#include<cstdio> 
#include<ctime> 
#include<cstring> 
#include<algorithm> 
inline int read() { 
    int x = 0,f = 1; 
    char c = getchar(); 
    while(c < '0' || c > '9')c = getchar(); 
    while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
    return x * f; 
}
const int maxn = 13; 
#define INF 0x7fffffff
int n,m;
int mp[maxn][maxn]; 
#define IT = 5; 
struct node { 
    int u,v,w,next; 
    bool operator < (const node & a)const { 
        return w < a.w; 
    } 
} E[maxn * maxn],edge[maxn * maxn]; 
int num = 0,head[maxn]; 
inline void add_edge(int u,int v,int w) { 
    edge[++ num].v = v; edge[num].w = w; edge[num].next = head[u];head[u] = num; 
} 
int fa[maxn]; 
int find(int x) { 
    if(fa[x] != x) fa[x] = find(fa[x]); 
    return fa[x]; 
} 

int f[maxn]; 
int tot = 0; 
int calc(int x,int fa,int num) { 
    int ans = 0; 
    for(int i = head[x];i;i = edge[i].next) { 
        int v = edge[i].v; 
        if(v == fa) continue; 
        ans += edge[i].w * num; 
        ans += calc(v,x,num + 1); 
    } 
    return ans; 
} 
#define T 100000
#define delta 0.97 
#define eps 1e-10
int solve() { 
    int ret = INF; 
    for(int i = 1;i <= n;++ i) fa[i] = i,head[i] = 0;  num = 0; 
    int cnt = 0;  
    for(int i = 1;i <= tot;++ i) { 
        int u = find(E[i].u),v = find(E[i].v); 
        if(u != v) { 
            fa[u] = v; 
            add_edge(E[i].u,E[i].v,E[i].w); 
            add_edge(E[i].v,E[i].u,E[i].w); 
            cnt ++; 
        }   
        if(cnt == n - 1) break; 
    } 
    if(cnt != n - 1) return INF; 
    for(int i = 1;i <= n;++ i) ret = std::min(ret,calc(i,i,1)); 
    return ret; 
} 
int main() { 
    srand(20010901); 
    n = read(),m = read(); 
    memset(mp,0x3f,sizeof mp); 
    for(int u,v,w,i = 1;i <= m;++ i) { 
        u = read(),v = read(),w = read(); 
        mp[u][v] = mp[v][u] = std::min(mp[u][v],w); 
    } 
    for(int i = 1;i <= n;++ i) 
        for(int j = i + 1;j <= n;++ j) 
        if(mp[i][j] < 0x3f3f3f3f) E[++ tot] = (node) {i,j,mp[i][j]}; 
    if(tot == 0) { 
        printf("0"); 
        return 0; 
    } 
    std::sort(E + 1,E + tot + 1); 
    int ans = solve(); 
    
    for(int i = 1;i <= 200;++ i) { 
        int now = INF; double t = T; 
        for(;t > eps;t *= delta) { 
            int loc1 = rand() % tot + 1,loc2 = rand() % tot + 1; 
            std::swap(E[loc1],E[loc2]);  
            int nxans = solve(); 
            if(nxans < now || (exp(now - nxans / t) < (rand() / RAND_MAX))) now = nxans; 
            else std::swap(E[loc1],E[loc2]);  
        } 
        ans = std::min(ans,now); 
    } 
    printf("%d\n",ans); 
    return 0; 
} 
 
 
  

luogu P3959 宝藏

标签:fine   ons   ||   lse   dom   math   max   oid   exp   

原文地址:https://www.cnblogs.com/sssy/p/9643345.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!