社会关系网络&并查集

来源:互联网 发布:mac如何对u盘格式化 编辑:程序博客网 时间:2024/05/16 07:00

描述

 

现代社会通信便捷,借助于Internet形成了各式各样的社区,每个人都可能属于多个社交圈,尤其是Facebook类社交网站的出现,使世界缩小了,人与人的交往扩大了频繁了。sed同学正在做这方面的毕业设计课题,指导老师给他布置了一个任务:已知一群人的社会关系网络,判断两个人之间的关系,他们是否可以通过社交圈的人相互结识。

 

输入

 

第一行包括三个整数:n、 m、k,分别表示人数、社区数、查询两个人之间的关系的用例数 (1 ≤ n ≤ 10000, 0 ≤ m ≤ 100,1 ≤ k ≤ 100)。

m行,每行首先给出一个社区的人数,然后给出代表人的序号。

k行,每行给出待查询的两个人(用序号表示)。

 

输出

 

   输出k行,每行给出两个人(用序号表示)、YES或NO, YES表示这两个人可以通过社交圈的人相互结识,NO表示不能。

 

注意:输出部分的结尾要求包含一个多余的空行。

 

样例输入

3 1 2

2 1 2

0 1

1 2

样例输出

0 1 NO

1 2 YES

并查集(union-find)适用于此类n个元素的集合应用问题。将每个元素都划归到存正直接或间接关系的集合中,通过find()函数就可以判断两个元素是否属于同一集合了。

#include <iostream>#include <list>#include <vector>using namespace std;int p[10001];int find(int x){int m=x,t;while(m!=p[m]) m=p[m];//m为查找的元素,p[m]为m所指向的那个元素while(x!=m)//将要查询的节点挂到根节点下,提高效率{t=p[x];p[x]=m;x=t;}return x;}void union1(int x,int y){int a,b;a=find(x);b=find(y);if(a==b)return;p[a]=b;//将a挂到b上}int _tmain(int argc, _TCHAR* argv[]){int n,m,k,i,num,a,b;while(scanf("%d%d%d",&n,&m,&k)!=EOF){for(i=0;i<n;++i)p[i]=i;while(m--){scanf("%d",&num);scanf("%d",&a);num--;while(num--){scanf("%d",&b);if(find(a)!=find(b))//将输入的第一个元素a和之后的元素进行unionunion1(find(a),find(b));}}while(k--){scanf("%d%d",&a,&b);if(find(a)==find(b))cout<<a<<" "<<b<<" "<<"YES"<<endl;elsecout<<a<<" "<<b<<" "<<"NO"<<endl;}}return 0;}


0 0
原创粉丝点击