http://acm.hdu.edu.cn/showproblem.php?pid=1232
这道题是学习并查集的第一道题。
并查集,他的思路是构成一个树结构,如果这两个节点的根节点相同,那么说明这两个节点在一个集合里,否则不再一个集合。
查找根节点:当然是递归查找他上一层的父节点是什么。知道查找到的节点的父节点是他本身为止。
int find(int x) { return par[x] == x ? x : par[x] = find(par[x]); }
将节点加入集合:为了方便查找,直接将节点连接到树的根节点上就可以了。
void unite(int x,int y){x=find(x);y=find(y);if(x==y)return;par[x]=y;}
下面说一下题意:
这道题是希望所有点连通,那么就是希望所有点都在一个集合里。
所以最多的起始路径数应该是n-1(即所有点都连接到根节点上),根据已知的已经连接的路,如果在一个集合那么就返回,不再一个集合就把他们放在一个集合里,然后路径数减一。
#include<stdio.h> int par[1001]; int ans; int k,n,m,a,b; int find(int x); void unio(int x,int y); int main(){while(~scanf("%d",&n)&&n!=0){scanf("%d",&m);for(int i=1;i<n+1;i++){par[i]=i;}k=n-1;for(int i=0;i<m;i++){scanf("%d%d",&a,&b);unio(a,b);} printf("%d\n",k);}return 0; } //两种查找根节点 int find(int x){while(par[x]!=x){x=par[x];}return x; } //int find(int x) //{ // return par[x]==x?x:(par[x]=find(par[x])); //} //联结两个点 void unio(int x,int y){x=find(x);y=find(y);if(x==y)return;k--;par[x]=y;}