题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=1232
题意就是问至少还要建多少个道路能将所有的城镇连接在一起。
用并查集将连在一起的城镇合并在一起,求出有多少个这样的集合-也就是多少个强连通通路。
强连通通路个数-1 即为答案。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
using namespace std;
/*
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
*/
int n,m;//n个点,总共有m跳边,单向边
int visit[1005];
int maps[1005][1005];
int parent[1005];//父亲节点
void UFset()
{
for(int i=0;i<=n;i++)
parent[i]=i;
}
int find(int x)
{
int r=x;
while(x!=parent[x])
x=parent[x];
while(r!=x)
{
int j=parent[r];
parent[r]=x;
r=j;
}
return x;
}
void xiaohao()
{
int i,j;
UFset();//初始化父亲节点
for(i=1;i<=n;i++)
{
for(j=i+1;j<=n;j++)//因为前面写的是a<b,所以这里不能是for(j=1;j<i;j++)
{
if(maps[i][j])//i和j之间有路
{
int fi=find(i),fj=find(j);
if(fi!=fj)
parent[fi]=fj;
}
}
}
}
int main()
{
int i,j;
while(cin>>n,n)
{
cin>>m;
memset(maps,0,sizeof(maps));
for(i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(a>b)//保证a<b
swap(a,b);
maps[a][b]=1;
}
xiaohao();
memset(visit,0,sizeof(visit));
int count=0;//计数,统计有多少个强连通通路
for(i=1;i<=n;i++)
{
int fi=find(i);
if(visit[fi]==0)//如果根节点未访问,每个根节点表示一个强连通通路
{
visit[fi]=1;
count++;
}
}
printf("%d\n",count-1);//强连通通路个数-1,因为2个强连通通路只需要建一条路就可以变成一个强连通通路
}
return 520;
}