luogu P3959 宝藏
Posted sssy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
",ans);
return 0;
}
以上是关于luogu P3959 宝藏的主要内容,如果未能解决你的问题,请参考以下文章