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; }
原文:http://www.cnblogs.com/Yvettey-me/p/4541218.html