題目大意:任意兩個點之間在不走回頭路的狀況下只有一條路聯通。ios
解題思路:只須要在基礎並查集的基礎上記錄是否造成了迴路,而後用一個set記錄節點與邊是否知足對應的關係就能夠了。數組
#include<iostream> #include<set> #include<algorithm>
using namespace std; const int N=100005; int f[N];//f數組記錄根節點
int Urank[N];//記錄根節點的秩,按秩合併的須要
int flag,grah;//當flag爲1時,表示造成了環
set<int> s;//記錄節點的集合
void init(int x)//初始化函數
{ for(int i=0;i<=x;i++) { f[i]=i; Urank[i]=0; } flag=0;//初始是無環的
grah=1; } int U_find(int x)//非遞歸的路徑壓縮查詢
{ int r,j,k; r=x; while(r!=f[r]) { r=f[r]; } k=x; while(k!=r) { j=f[k]; f[k]=r; k=j; } return r; } void U_merge(int x,int y)//按秩合併
{ x=U_find(x); y=U_find(y); if(x!=y) { if(Urank[x]<Urank[y]) { f[x]=y; }else { f[y]=x; if(Urank[x]==Urank[y])Urank[x]++; } }else flag=1;//當合並的二者根節點相同時,說明造成了環
} int main() { int a,b; while(cin>>a>>b)//多組輸入,輸入每一組的第一對數據
{ init(N);//初始化,由於已經輸入一對了,因此邊被初始化成1
if(a==0&&b==0)//當a與b都爲0時,說明是空樹,空樹也知足條件
{ cout<<"Yes"<<endl; } if(a==-1&&b==-1)//結束條件
{ break; } s.insert(a); s.insert(b);//將兩點插入集合中
if(!flag)//只要沒有出現環,就合併兩點
{ U_merge(a,b); } while(1)//在符合繼續輸入的條件下,開始讀完後續的數據
{ cin>>a>>b; if(a==0&&b==0)//單組數據終止條件
{ break; }else { s.insert(a); s.insert(b); if(!flag) { U_merge(a,b); } grah++;//上述操做同理,只不過要記得每次都要把邊的數量加一
} } if(!flag&&s.size()==grah+1)//沒有造成環且節點數等於邊數+1的狀況下知足條件
{ cout<<"Yes"<<endl; }else { cout<<"No"<<endl; } s.clear();//清空集合
} return 0; }