社會關係網絡&並查集

描述

 

現代社會通信便捷,藉助於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和之後的元素進行union
union1(find(a),find(b));
}
}
while(k--)
{
scanf("%d%d",&a,&b);
if(find(a)==find(b))
cout<<a<<" "<<b<<" "<<"YES"<<endl;
else
cout<<a<<" "<<b<<" "<<"NO"<<endl;
}
}
return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章