标签:
NOIP2013 提高组 day2 第三题
Kruskal算法是图论里求最小生成树的高效算法
借用并查集来巧妙的算最小生成树
思路是这样的:
先把所有的边排序,然后根据需要来依次合并权值最大(小)边的端点(或是计算路线中所有边中的最小值的最大值)
注 但是Kruskal并不能全过,只过得到60%,还有405要使用树上路径倍增,但暂时还没有掌握
题意就是只要有路把它们连起来,让这些路中的承重的最小值最大就可以了,可以使用Kruskal
注意并查集中的几个函数,很简单的,不要记错了
代码
#include<cstdio>
#include<iostream>//并查集 Kruskal
#include<algorithm>
using namespace std;
const int maxx=50005;
int fat[10001];
int n,q,tot,m;
struct xx{
int x,y,w;
}bian[maxx];
int father(int x)//寻找父亲
{
if(fat[x]!=x) fat[x]=father(fat[x]);
return fat[x];
}
void unionn(int a,int b)//注意并查集是把父亲相连
{
int fa=father(a);
int fb=father(b);
if(fa!=fb) fat[fa]=fb;
}
bool cmp(const xx a,const xx b)
{
return b.w<a.w;
}
int main()
{
freopen("truck.in","r",stdin);
freopen("truck.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
bian[i].x=x,bian[i].y=y,bian[i].w=z;
}
sort(bian+1,bian+m+1,cmp);
cin>>q;
for(int i=1;i<=q;i++)
{int x,y,minn=1e6,k=1;
for(int i=1;i<=n;i++)fat[i]=i;//初始化
scanf("%d %d",&x,&y);
for(int i=1;i<=m;i++)
{
if(father(x)==father(y)){
printf("%d\n",minn);
break;
}
else if(father(bian[i].x)!=father(bian[i].y))
{
unionn(bian[i].x,bian[i].y);
//if(bian[i].w<minn)//这步其实没必要
minn=bian[i].w;
}
}
if(father(x)!=father(y))printf("-1\n");
}
return 0;
}
标签:
原文地址:http://www.cnblogs.com/lwhinlearning/p/5665048.html