HUD1232畅通工程(并查集)

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 
Input测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。 
注意:两个城市之间可以有多条道路相通,也就是说 
3 3 
1 2 
1 2 
2 1 
这种输入也是合法的 
当N为0时,输入结束,该用例不被处理。 
Output对每个测试用例,在1行里输出最少还需要建设的道路数目。 
Sample Input
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
Sample Output
1
0
2
998


        
  
Huge input, scanf is recommended.
Hint
Hint
        

分析

并查集,先初始化根节点为自己本身,否则会造成无法寻找到根节点

构建连通图,把所给数据连入连通图,形成原始并查集

循环遍历,寻找哪两座城市没有连通,连通之后继续寻找


#include<stdio.h>
int fd[1010],s[1010][2];
int find(int x)//并查集
{
    if(fd[x]==x)
        return x;
    return fd[x]=find(fd[x]);
}
int main()
{
    int m,n,i,j,t;
    while(scanf("%d%d",&n,&m)&&n!=0)
    {
        for(i=1; i<=n; i++)//初始化根节点
            fd[i]=i;
        for(i=0; i<m; i++)
        {
            scanf("%d%d",&s[i][0],&s[i][1]);
            int a=find(s[i][0]);
            int b=find(s[i][1]);
            if(a!=b)//合并组别
                fd[a]=b;
        }
        t=0;
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
            {
                int a=find(i);//双向连通,所以寻找根节点,无需考虑所处层数
                int b=find(j);
                if(a!=b)//查找没有连通的两个村庄
                {
                    t++;
                    fd[a]=b;//把它们联通, 避免重复计算
                }
            }
        printf("%d\n",t);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章