UVa - 1395 - Slim Span(Kruskal算法+并查集,最小生成树)

来源:互联网 发布:js点击触发事件 方法名 编辑:程序博客网 时间:2024/05/22 03:12





思路:题目要求求出边权值的最大值和最小值的差值,该差值是最小的。最小生成树,Kruskal算法和Prim算法其中Kruskal算法中的贪心策略,将边权从小到大排列,因此用Kruskal算法来求解。在生成最小生成树的时候,在范围[L,R]中,其中L是最小边权,将求权值的和改为求w[L]-w[R],然后一次更新L的值,遍历所有的情况,更新最小值即可。

注:其中给出的结点的编号是从1开始的,所以并查集的下标要从1-n都更新。


/**Kruskal算法(最小生成树) */#include<cstdio>#include<algorithm>#define N 10010#define INF 999999999using namespace std;int u[N],v[N],w[N],p[N],r[N];int n,m;bool cmp(int i,int j){return w[i]<w[j];}int find(int x){//并查集find return p[x]==x?x:p[x] = find(p[x]);}int Kruskal(){int ans = INF;for(int i=0 ;i<m ;i++)r[i]=i;// 将路径编号 sort(r,r+m,cmp);//排序 for(int i=0 ;i<m ;i++){for(int x=0 ;x<=n ;x++)p[x]=x;//并查集初始化 int cnt = 0,temp=0;//cnt来记录结点的个数 for(int j=i ;j<m ;j++){int e = r[j];int x = find(u[e]);int y = find(v[e]);if(x!=y){p[x] = y;cnt++;if(cnt==n-1){temp = w[r[j]] - w[r[i]];ans = min(ans,temp);break;}}} }if(ans!=INF)printf("%d\n",ans);elseputs("-1");}int main(){while(scanf("%d%d",&n,&m)!=EOF){if(n==0&&m==0)break;for(int i=0 ;i<m ;i++){scanf("%d%d%d",&u[i],&v[i],&w[i]);}Kruskal();}return 0;} 



1 0