题目:宗教问题
第一行输入n(人数),m(关系数)
接着换行输入m个关系
换行输入询问次数q
换行输入询问每组询问对应一组输出:如果是则输出YES,否或不一定都输出NO
例:
5 3 ,5个人,3个关系
1 2 1说他在自己的教堂里看到过2
2 3 2说他在自己的教堂里看到过3
4 5 4说他在自己的教堂里看到过5
2 2组询问次数
1 3 问:1和3是同一个教堂吗? 输出YES
1 5 问:1和5是同一个教堂吗? 输出NO
#include<stdio.h>
int tree[1000];
int find(int x)
{
return tree[x]==x?x:find(tree[x]);
}
void uset(int a, int b)
{
a=find(a);
b=find(b);
if(a==b)
return ;
tree[b]=a;
}
int main()
{
int n,i,m,a,b;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
tree[i]=i;
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
uset(a,b);
}
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
if(find(a)==find(b))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
压缩路径:查找过的节点都直接连到根上,降低树的高度,所以递归查找时深度遍历的
层数降低了,所以越用越快
#include<stdio.h>
int tree[1000];
int find(int x)
{
return tree[x]<0?x:(tree[x]=find(tree[x]));
}
void uset(int a, int b)
{
if((a=find(a))==(b=find(b)))
return ;
if(tree[a]<tree[b])
tree[b]=a;
else if(tree[a]>tree[b])
tree[a]=b;
else
{
tree[a]=b;
tree[b]--;
}
}
int main()
{
int n,i,m,a,b;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
tree[i]=-1;
for(i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
uset(a,b);
}
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
if(find(a)==find(b))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}