【NOJ1593、1594、1595】【並查集三連】朋友敵人關係
阿新 • • 發佈:2018-12-13
1593.並查集(一)
時限:1000ms 記憶體限制:10000K 總時限:3000ms
描述
一個城市中有n個人,其中一些人是朋友關係,同時他們都認為:朋友的朋友是朋友,現在任給兩個人,問他們是否是朋友關係。
輸入
先輸入兩個正整數n和m(均小於1000),表示城市裡有n個人,並且將給出m對朋友關係,接下來的m行每行給出兩個0~n-1之間的整數,表示這兩個人是朋友關係。 最後一行再輸入兩個0~n-1之間的整數,問他們是否是朋友關係。
輸出
是朋友關係則輸出"Yes",否則輸出"No"。
#include <iostream> using namespace std; int a[1000]; //儲存並查集 int n,m; int fsearch(int x); //返回結點x的根節點 int main() { //輸入資料 cin>>n>>m; for(int i=0;i<n;i++) { a[i]=i; //初始時每個人只和自己做朋友 } int x,y; //是朋友關係的兩個人 int kx,ky; //根節點 for(int i=0;i<m;i++) { cin>>x>>y; //cout<<x<<y; kx=fsearch(x); //x的根節點 ky=fsearch(y); //y的根結點 a[ky]=kx; //相連 } //輸出資料 cin>>x>>y; kx=fsearch(x); //x的根節點 ky=fsearch(y); //y的根結點 if(kx==ky) { cout<<"Yes"<<endl; } else { cout<<"No"<<endl; } return 0; } int fsearch(int x) { int f=a[x]; while(f!=a[f]) //若未找到根節點 { f=a[f]; //繼續向上搜尋 } a[x]=f; //更新a[x]的值,使他離根節點更近,方便下一次搜尋 return f; }
1594.並查集(二)
時限:1000ms 記憶體限制:10000K 總時限:3000ms
描述
一個城市中有一些犯罪團伙,共有n個人,有m條資訊同夥資訊,並且知道同夥的同夥是同夥,問共有多少個犯罪團伙。
輸入
先輸入兩個正整數n和m(均小於1000),表示城市裡有n個人,並且將給出m對朋友關係,接下來的m行每行給出兩個0~n-1之間的整數,表示這兩個人是朋友關係。
輸出
輸出犯罪團伙的個數。
#include <iostream> using namespace std; int a[1000]; //儲存並查集-犯罪團伙 int n,m; int fsearch(int x); //返回x結點的根節點 int main() { cin>>n>>m; for(int i=0; i<n; i++) //初始化並查集 { a[i]=i; } int x,y; int kx,ky; for(int i=0; i<m; i++) //讀入資料 { cin>>x>>y; kx=fsearch(x); ky=fsearch(y); a[ky]=kx; } int cnt=0; //犯罪團伙個數 for(int i=0; i<n; i++) { if(a[i]==i) //數根節點個數 { cnt++; } } cout<<cnt<<endl; return 0; } int fsearch(int x) //返回x結點的根節點 { int f=x; while(f!=a[f]) { f=a[f]; } a[x]=f; //使x結點直接指向其根節點 return f; }
1595.並查集(三)
時限:1000ms 記憶體限制:10000K 總時限:3000ms
描述
一個城市中有n個人,其中一些人是朋友關係,一些人之間是敵人關係,同時他們都認為:朋友的朋友是朋友,敵人的敵人是朋友,(注意:朋友的敵人不一定是敵人),現在任給兩個人,問他們是否是朋友關係。
輸入
先輸入兩個正整數n和m(均小於1000),表示城市裡有n個人,並且將給出m對朋友或敵人關係,接下來的m行每行三個整數,先給出一個整數0或1(0表示後面這兩個人是朋友,1表示是敵人),再給出兩個0~n-1之間的整數表示兩個人。 最後一行再輸入兩個0~n-1之間的整數,問這兩個人是否是朋友關係。
輸出
是則輸出"Yes",否則輸出"No"。
#include <iostream>
using namespace std;
int a[1000]; //朋友並查集
int b[1000][1000]; //儲存敵人關係
int n,m;
int fa_search(int x); //返回並查集a裡x的根節點
void fa_add(int x, int y); //將x和y新增成朋友關係
void fb_add(int x, int y); //將x和y新增成敵人關係
void f_add(int x, int y); //將y的敵人與x新增成朋友關係
//(敵人的敵人是朋友)
int main()
{
cin>>n>>m;
for(int i=0; i<n; i++) //初始化並查集
{
a[i]=i;
}
int p,x,y;
int kx,ky;
for(int i=0; i<m; i++) //輸入資料
{
cin>>p>>x>>y;
if(p==0) //x和y是朋友
{
fa_add(x, y);
}
else //x和y是敵人
{
//在b中新增敵人關係
fb_add(x, y);
//y的所有敵人是x的朋友
f_add(x, y);
//x的所有敵人是y的朋友
f_add(y, x);
}
}
cin>>x>>y;
kx=fa_search(x);
ky=fa_search(y);
if(kx==ky) //輸出資料
{
cout<<"Yes"<<endl;
}
else
{
cout<<"No"<<endl;
}
return 0;
}
int fa_search(int x) //返回並查集a裡x的根節點
{
int f=a[x];
while(f!=a[f])
{
f=a[f];
}
a[x]=f; //更新a[x]
return f;
}
void fa_add(int x, int y) //將x和y新增成朋友關係
{
int kx,ky;
kx=fa_search(x);
ky=fa_search(y);
a[ky]=kx;
}
void fb_add(int x, int y) //將x和y新增成敵人關係
{
b[x][y]=1;
b[y][x]=1;
}
void f_add(int x, int y) //將y的敵人與x新增成朋友關係
{ //(敵人的敵人是朋友)
for(int i=0; i<n; i++)
{
if(i!=x&&i!=y)
{
if(b[y][i]==1) //若y和i是敵人關係
{
fa_add(x,i); //那麼x和i是朋友關係
}
}
}
}
【後記】
1.並查集(四)吭哧半天沒寫出來,好氣啊,待續