hdu3371Connect the Cities(并查集,最小生成树)

来源:互联网 发布:靠谱的淘宝小样店 编辑:程序博客网 时间:2024/06/05 15:57

1.题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3371

 

2.思路:

       给出n个点,m条边,以及k组已经修好的路,问联通所有城市要需要至少多少的修路费。

 

3.参考代码:

代码一:并查集

 

#include <stdio.h>#include <algorithm>using namespace std;#define N 505int root[N];struct node{int u,v,w;}edge[N*N];int cmp(node x,node y){return x.w<y.w;}int find(int x){if(x==root[x])return x;return root[x]=find(root[x]);}int main(){int t,n,m,k,i,x,y,num,rt,a,ans;scanf("%d",&t);while(t--){for(i=0;i<=N;i++)   ///一定要从0开始,不然会WAroot[i]=i;   ///初始化并查集int flag=0;scanf("%d%d%d",&n,&m,&k);for(i=1;i<=m;i++)scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);sort(edge+1,edge+m+1,cmp);   ///将边排序while(k--){scanf("%d%d",&num,&rt);for(i=1;i<num;i++){scanf("%d",&a);x=find(a);y=find(rt);if(x!=y)root[x]=y;}}for(num=0,i=1;i<=n;i++){if(root[i]==i)num++;}for(ans=0,i=1;i<=m;i++){x=find(edge[i].u);y=find(edge[i].v);if(x!=y){root[x]=y;ans+=edge[i].w;num--;}if(num==1)   ///num==1说明只有能够并成一棵树{flag=1;break;}}if(flag)printf("%d\n",ans);elseprintf("-1\n");}return 0;}


 

 

 

代码二:prime算法

 

#include <stdio.h>#define inf 0xffff#define N 505int n,m;int edge[N][N];int lowcost[N];   ///记录最低费用int vis[N];void prime(){sum=0,cnt=0;for(i=1;i<=n;i++){lowcost[i]=edge[1][i];vis[i]=0;}vis[1]=1;for(i=1;i<=n;i++){int min=inf;for(j=1;j<=n;j++){if(min>lowcost[j] && !vis[j]){min=lowcost[j];pos=j;}}vis[pos]=1;sum+=min;cnt++;   ///边数加一if(min==inf)break;for(j=1;j<=n;j++){if(lowcost[j]>lowcost[pos]+edge[pos][j] && !vis[j])lowcost[j]=lowcost[pos]+edge[pos][j];}}if(cnt==n-1)   ///边数等于点数加一printf("%d\n",sum);elseprintf("-1\n");}int main(){int t,k,i,j,u,v,w,num,a[111111];scanf("%d",&t);while(t--){scanf("%d%d%d",&n,&m,&k);for(i=1;i<=n;i++){for(j=1;j<=m;j++)edge[i][j]=inf;}while(m--){scanf("%d%d%d",&u,&v,&w);if(edge[u][v]>w)edge[u][v]=edge[v][u]=w;}while(k--){scanf("%d",&num);for(i=1;i<=num;i++)scanf("%d",&a[i]);for(i=1;i<=num;i++){for(j=1;j<=num;j++){if(i!=j)edge[a[i]][a[j]]=edge[a[j]][a[i]]=0;}}}prime();}return 0;}