hdu 1232 畅通工程
2012-11-23
今天复习了一下并查集,然后这道题才发现当时是傻掉了,其实就是并查集找有多少个连通分量,有c个连通分量的话要把他们连起来就需要c-1条边,根本不需要kruskal算法…………………………
#include <cstdio> #include <cstring> #define N 1010 int p[N]; int n,m; int find(int x) { return p[x]==x ? x : p[x]=find(p[x]); } int main() { while(scanf("%d",&n) && n) { for(int i=1; i<=n; i++) p[i]=i; scanf("%d",&m); for(int i=1; i<=m; i++) { int u,v,x,y; scanf("%d%d",&u,&v); x=find(u); y=find(v); if(x!=y) p[x]=y; } int count=0; for(int i=1; i<=n; i++) if(p[i]==i) count++; printf("%d\n",count-1); } return 0; }
//最小生成树裸题
//给出已经存在的边(输入中可能重复但是不影响),然后问你要构建出最小生成树还需要//多少条边
//用kruskal算法显然更合理并且方便,已经存在的边保存在边集数组中,然后看看这些已
//经存在的边有多少条是可以纳入的(因为已经存在的边如果全部纳入的话可能有环)
//没纳入一条边我们就在count中计数,扫描完边集数组后,就可以已经纳入了多少条边
//即count,然后还需要的边就是n-1-count,因为由最小生成树的性质可知边数一定是n-1
//题目很容易,不要进去惯性思维与权值扯上关系,这道题与权值无关,其实是考察了最小//生成树成环的问题,边集数组中只需要保存边的两个点即可,不需要知道权值
#include <stdio.h> #include <string.h> #define MAX 1100 struct edge { int b,e; }a[MAX*MAX]; int count,n,m; int p[MAX]; int find(int x) { return p[x]==x ? x : p[x]=find(p[x]) ; } int main() { int i,j,x,y; while(scanf("%d",&n)!=EOF && n) { scanf("%d",&m); for(i=1; i<=m; i++) scanf("%d%d",&a[i].b,&a[i].e); for(i=1; i<=n; i++) p[i]=i; for(count=0,i=1; i<=m; i++) { x=find(a[i].b); y=find(a[i].e); if(x!=y) { p[x]=y; count++; } } printf("%d\n",n-1-count); } return 0; }