当前位置: 代码迷 >> 综合 >> UVa - 1395 - Slim Span(Kruskal算法+并查集,最小生成树)
  详细解决方案

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

热度:90   发布时间:2023-10-09 17:36:47.0



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


思路:题目要求求出边权值的最大值和最小值的差值,该差值是最小的。最小生成树,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 999999999
using 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;
} 



  相关解决方案