这两题主要是解决一个图是否是树的问题。
有很多细节需要注意。
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"; else cout<<"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)); //标志在图内的点,在为true memset(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]++; //入度加1 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); 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."; else cout<<"Case "<<cas++<<" is not a tree."; cout<<endl; } return 0; }