这两题主要是解决一个图是否是树的问题。
有很多细节需要注意。
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;
}