畅通工程 HDU - 1232

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路? 

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

题意理解:这是并查集的经典入门题目,也是并查集的裸题,只需要知道连通块的数量,就可以进而得到需要连通块的数量减1条路径就可以把所有连通块连通,这里,我们也可以反过来想,假设最开始所有点都是连在一起的,没有环,可以想象成所有点一字排开,一笔划去连起来,起始边的数量是N-1,然后没次两个点JOIN,就删去一条边,最后得到的就是答案。

代码:

#include 
#include 
#include 

using namespace std;

int pre[1005];

int Find(int root)
{
    int  son, temp;
    son = root;
    //找根结点
    while(root != pre[root])   root = pre[root];
    while(son != root)    //路径压缩
    {
        temp = pre[son];
        pre[son] = root;
        son = temp;
    }
    return root;
}

void Join(int root1, int root2)
{
    int x, y;
    x = Find(root1);
    y = Find(root2);
    if(x != y)  //判断是否属于一个连通块
        pre[x] = y;
}

int main()
{
    int N, M, px, py, rx, ry;
    while(cin >> N && N)
    {
        int ans = N-1;
        cin >> M;
        for(int i = 1; i <= N; i++)
            pre[i] = i;
        while(M--)
        {
            cin >> px >> py;
            rx = Find(px);
            ry = Find(py);
            if(rx != ry)
            {
                pre[rx] = ry;
                ans--;
            }
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

你可能感兴趣的:(并查集)