专题四1003

来源:互联网 发布:网络上说的384什么意思 编辑:程序博客网 时间:2024/05/29 00:30

题目大意:

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

输入:第一行有两个正整数N和M,N代表城镇数,即节点数,M代表已经有的道路数,即已有边数,然后接下里的M行没行输入两个正整数,代表这每一条边的两个端点。测试实例有多个,当输入的N为0时,程序结束

输出:

每一行输出一个整数,代表每一个测试实例的答案。

解题思路:

这是一道中文题目,因此题意理解起来应该挺简单的,就是问在现有道路的基础上需要再建设多少条道路使得所有城镇可以联通起来。我先把题目上的例子在纸上花了出来,彻底理解了题意。把城镇当成节点,道路理解为两个节点之间的边,然后这就是一个图,如果这个图联通的话,那么这个实例的答案就是0,反之,答案就是不连通的子图的数量-1。既然这样的话,就用并查集的方法求出有多少个连通分量即可。首先定义了一个整形数组并从下标1开始初始化,值即为下标,代表第i个节点在第i个集合中,之后根据输入的每条边的两个节点将这两个节点进行合并,查出这两个节点所在的集合,如果不相等的话再进行合并,一个合并到另一个,然后知道每条已有边全都合并。这时候定义一个整形变量count=-1,然后for循环从1到n检查第i个节点所在的集合是否为i,是的话,count++,否则不动。输出count即为答案,这里一定要记住count初值从-1开始,因为如果有两个连通分量的话只需要再加一条额外的边就可以实现连通,以此类推。

感想:

感觉这道题目并不难,真正的理解了它的意思之后运用并查集的知识还是很简单的。

AC代码:

#include<iostream>

using namespacestd;

int city[1001];

int findx(intx)

{

    intr=x;

    while(city[r]!=r)

    {

        r=city[r];

    }

    returnr;

}

void merge(inta,intb)

{

    intfx=findx(a);

    intfy=findx(b);

    if(fx!=fy)

        city[fx]=fy;

}

int main()

{

    intn,m,start,end,count,j;

    while(cin>>n)

    {

        if(n==0)

            break;

        cin>>m;

        for(inti=1;i<=n;i++)

            city[i]=i;

        for(inti=1;i<=m;i++)

            {

                cin>>start>>end;

                merge(start,end);

        }

        for(count=-1,j=1;j<=n;j++)

        {

            if(city[j]==j)

                count++;

        }

        cout<<count<<endl;

    }

    return0;

}

0 0
原创粉丝点击