病毒 | ||||||
| ||||||
Description | ||||||
某种病毒袭击了某地区,该地区有N(1≤N≤50000)人,分别编号为0,1,...,N-1,现在0号已被确诊,所有0的直接朋友和间接朋友都要被隔离。例如:0与1是直接朋友,1与2是直接朋友,则0、2就是间接朋友,那么0、1、2都须被隔离。现在,已查明有M(1≤M≤10000)个直接朋友关系。如:0,2就表示0,2是直接朋友关系。 | ||||||
Input | ||||||
第一行包含两个正整数N(1≤N≤50000),M(1≤M≤100000),分别表示人数和接触关系数量; | ||||||
Output | ||||||
输出数据仅包含一个整数,为共需隔离的人数(包含0号在内)。 | ||||||
Sample Input | ||||||
100 4 | ||||||
Sample Output | ||||||
3 |
#include <stdio.h>
int pre[50011];
int find(int x) //查找
{
int r=x;
while (r!=pre[r])
r=pre[r]; //找到他的前导节点
int j=x;
int t;
while (pre[j]!=r) //路径压缩
{
t=pre[j]; //记录x的前导节点
pre[j]=r; //将j的前导节点设置为r的根节点
j=t;
}
return r;
}
//路径压缩为了加快查找的速度,将x点与其根节点直接相连,够造成类似于只有叶子节点而没有分支节点的树
void join(int x,int y)
{
int fx,fy;
fx=find(x); //x的根节点为fx
fy=find(y); //y的根节点为fy
if (fx!=fy) //如果fx,fy不是相同的根节点,说明fx,fy不是连通的
pre[fx]=fy; //我们将fx,fy连通,我们将fx的前导节点设置为fy
}
int main()
{
int n,m;
int t1,t2;
int ans;
int root;
scanf ("%d %d",&n,&m);
//首先初始化:我们将每一个节点的前导节点设置为自己,如果在join函数时未能形成连通,将独立成点
for (int i=0; i<n; i++) //n表示输入节点个数
{
pre[i]=i; //将每一个节点的前导节点设置为自己
}
for (int i=1; i<=m; i++)
{
scanf ("%d%d",&t1,&t2);
join(t1,t2);
}
root=find(pre[0]); //0的根
ans=0;
for (int i=0; i<n; i++)
{
if (find(pre[i])==root)
ans++;
}
printf ("%d\n",ans);
return 0;
}