這兩題主要是解決一個圖是否是樹的問題。
有很多細節需要注意。
1、空樹也是樹。
2、一個圖若是樹需滿足兩個條件:
①連通分量為一;
②圖中無環,包括自環和非自環。
3、邊數+1=頂點數。
以上幾點只是針對無向圖的,1272題就是解決無向圖是否是樹的問題。而如果要判斷有向圖是否是樹,還要判斷
頂點的入度。滿足入度為0的點只有一個,以及入度都不大於1。1325題就是判斷有向圖是否是樹的問題。
1272 AC代碼:
#include<iostream>using namespace std;const int MAX=100001;int father[MAX];bool flag[MAX],flagLC;void initial() //初始化{for(int i=1;i<MAX;i++)father[i]=i;}int find(int x) //尋找{while(father[x]!=x)x=father[x];return x;}void combine(int a,int b) //合并{int tmpa=find(a);int tmpb=find(b);if(tmpa!=tmpb)father[tmpa]=tmpb;else flagLC=true; //a,b在同一個連通分量中,說明有環}int main(){int i,a,b,connectedComponent,edgeNum,nodeNum;bool flagCircle; //自環while(1){initial();edgeNum=0; //邊數flagLC=flagCircle=false; //標誌是否有環 memset(flag,false,sizeof(flag)); //標誌在圖內的點,在為true scanf("%d%d",&a,&b);if(a==0 && b==0) //空樹{cout<<"Yes"<<endl;continue;}if(a==-1 && b==-1) break;if(a==b) flagCircle=true;flag[a]=true;flag[b]=true; edgeNum++; combine(a,b);while(1){scanf("%d%d",&a,&b);if(a==0 && b==0) break; if(a==b) flagCircle=true;flag[a]=true;flag[b]=true; edgeNum++;combine(a,b);}connectedComponent=0; //連通分量數 nodeNum=0; //點數for(i=1;i<MAX;i++) //判斷圖是否連通,tmp=1連通{if(flag[i]){nodeNum++; //計算圖內包含的所有點if(father[i]==i)connectedComponent++;}}if(connectedComponent==1 && nodeNum==edgeNum+1 && !flagCircle && !flagLC) //連通的無環圖為樹cout<<"Yes";elsecout<<"No";cout<<endl;}return 0;}
1325 AC代碼:
#include<iostream>using namespace std;const int MAX=100001;int father[MAX];bool flag[MAX],flagLC;int in[MAX]; //存放頂點入度void initial() //初始化{for(int i=1;i<MAX;i++)father[i]=i;}int find(int x) //尋找{while(father[x]!=x)x=father[x];return x;}void combine(int a,int b) //合并{int tmpa=find(a);int tmpb=find(b);if(tmpa!=tmpb)father[tmpa]=tmpb;else flagLC=true; //a,b在同一個連通分量中,說明有環}int main(){int i,a,b,connectedComponent,edgeNum,nodeNum,cas=1;bool flagCircle; //自環while(1){initial();edgeNum=0; //邊數flagLC=flagCircle=false; //標誌是否有環 memset(flag,false,sizeof(flag)); //標誌在圖內的點,在為truememset(in,0,sizeof(in)); scanf("%d%d",&a,&b);if(a==0 && b==0) //空樹{cout<<"Case "<<cas++<<" is a tree."<<endl;continue;}if(a<0 && b<0) break;if(a==b) flagCircle=true;flag[a]=true;flag[b]=true; edgeNum++; combine(a,b);in[b]++; //入度加1while(1){scanf("%d%d",&a,&b);if(a==0 && b==0) break; if(a==b) flagCircle=true;flag[a]=true;flag[b]=true; edgeNum++;combine(a,b);in[b]++; //入度加1}connectedComponent=0; //連通分量數 nodeNum=0; //點數for(i=1;i<MAX;i++) //判斷圖是否連通,tmp=1連通{if(flag[i]){nodeNum++; //計算圖內包含的所有點if(father[i]==i)connectedComponent++;}}int numZero=0,numMore=0;for(i=0;i<MAX;i++){if(flag[i]){if(in[i]==0) //入度為0的點即根只能有一個numZero++;else if(in[i]>1) //不能有入度大於1的點numMore++;}}if(connectedComponent==1 && nodeNum==edgeNum+1 && !flagCircle && !flagLC && numZero==1 && numMore==0) //連通無環並且滿足入度條件 cout<<"Case "<<cas++<<" is a tree.";elsecout<<"Case "<<cas++<<" is not a tree.";cout<<endl;}return 0;}