标签:
1 6 4 3 1 4 2 2 6 1 2 3 5 3 4 33 2 1 2 2 1 3 3 4 5 6
1
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3371
题意:由于海平面上升,有一些城市消失了,有些城市间还有相连,但更多的城市间的已经不相连了,现在政府要修建一些路,使得所有的城市都相连,问你将所有城市连接起来还要花费多少钱。
输入n,m,k,分别代表城市总数,可修建的路的条数,现在任然连接的城市数。
接下来的m行各有三个数,分别代表两个城市间修路的费用,
最后k行,每行第一个数字 t 代表后面的 t 个城市仍然相连。
一看就知道是最小生成树,但有点改动,因为有一部分已经相连。再用Kruskal算法的时候把还相连的城市用并查集连在一起,而用Prime算法的把还相连的城市之间的修路的费用记为0就可以了。
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; struct node { int s,e,w; } a[25000+5]; int n,m,k; int fa[505]; bool cmp(node a,node b) { return a.w<b.w; } int Find(int x) { if(fa[x]==x) return x; return fa[x]=Find(fa[x]); } int Kruskal() { sort(a+1,a+m+1,cmp); int ans=0; for(int i=1; i<=m; i++) { int x=Find(a[i].s); int y=Find(a[i].e); if(x!=y) { ans+=a[i].w; fa[x]=y; } } return ans; } int main() { int T; cin>>T; while(T--) { cin>>n>>m>>k; for(int i=1; i<=m; i++) { scanf("%d%d%d",&a[i].s,&a[i].e,&a[i].w); } for(int i=1; i<=n; i++) fa[i]=i; for(int i=1; i<=k; i++) { int t,x,y; scanf("%d%d",&t,&x); for(int j=2; j<=t; j++) { scanf("%d",&y); int fx=Find(x); int fy=Find(y); if(fx!=fy) fa[fx]=fy; } } int ans=Kruskal(); int sum=0; for(int i=1; i<=n; i++) { if(fa[i]==i) sum++; } if(sum>1) cout<<"-1"<<endl; else cout<<ans<<endl; } return 0; }
#include <cstdio> #include <cstring> using namespace std; int a[505][505]; int dis[505]; bool vis[505]; int t[505]; const int INF=0x3f3f3f3f; int n,m,k; int Prime() { for(int i=1; i<=n; i++) { vis[i]=false; dis[i]=a[1][i]; } vis[1]=true; dis[1]=0; int ans=0; for(int i=1; i<n; i++) { int minn=INF; int p=-1; for(int j=1; j<=n; j++) { if(!vis[j]&&dis[j]<minn) minn=dis[p=j]; } vis[p]=true; if(p==-1) return -1; ans+=minn; for(int j=1; j<=n; j++) { if(!vis[j]&&dis[j]>a[p][j]) dis[j]=a[p][j]; } } return ans; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d%d%d",&n,&m,&k); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(i==j) a[i][j]=0; else a[i][j]=INF; } } int x,y,z; for(int i=1; i<=m; i++) { scanf("%d%d%d",&x,&y,&z); if(z<a[x][y]) a[x][y]=a[y][x]=z; } while(k--) { scanf("%d",&x); for(int i=1; i<=x; i++) { scanf("%d",&t[i]); } for(int i=1; i<x; i++) { for(int j=i+1; j<=x; j++) a[t[i]][t[j]]=a[t[j]][t[i]]=0; } } printf("%d\n",Prime()); } return 0; }
HDU 3371 Connect the Cities 【最小生成树,Prime算法+Kruskal算法】
标签:
原文地址:http://blog.csdn.net/hurmishine/article/details/52108142