首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点,让你判断它们是否连通,或者问你整幅图一共有几个连通分支,也就是被分成了几个互相独立的块。像畅通工程这题,问还需要修几条路,实质就是求有几个连通分支。如果是1个连通分支,说明整幅图上的点都连起来了,不用再修路了;如果是2个连通分支,则只要再修1条路,从两个分支中各选一个点,把它们连起来,那么所有的点都是连起来的了;如果是3个连通分支,则只要再修两条路……
以下面这组数据输入数据来说明
4 2 1 3 4 3
第一行告诉你,一共有4个点,2条路。下面两行告诉你,1、3之间有条路,4、3之间有条路。那么整幅图就被分成了1-3-4和2两部分。只要再加一条路,把2和其他任意一个点连起来,畅通工程就实现了,那么这个这组数据的输出结果就是1。
AC code
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5000 + 5;
int pre[maxn];
int n,m,p;
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 Union(int root1,int root2){
int x,y;
x=Find(root1);
y=Find(root2);
if(x!=y) //如果不连通
pre[y]=x; //让x做上级,谁做上级都一样,随便不影响
}
int main(){
cin>>n>>m>>p;
int a,b,x1,x2;
for (int i=1;i<=n;i++)
pre[i]=i;
while(m--){
cin>>a>>b;
Union(a,b);
}
for(int i=0;i<p;i++){ //一个一个找
cin>>a>>b;
if (Find(a)!=Find(b))
cout<<"No"<<endl;
else
cout<<"Yes"<<endl;
}
return 0;
}
//小分析
/* 1 2 3 4 5
1 1 1 1 4
1*/