大致題目:給定若干條邊,邊爲有向邊<u,v>從u指向v,由此判斷該圖是否爲一棵樹。簡單的並查集判斷迴路+樹特性判定
分析如下:首先用並查集檢查所有有向邊組成的圖是否存在迴路。若存在迴路則可以判定爲不是樹。同時在記錄下來每個頂點的入度和出度,一個沒有迴路的圖要成爲樹,充分必要條件:
1)有且僅有一個出度爲1的頂點,即爲根節點
2)其餘頂點的入度均爲1
下面是代碼:168K+0MS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define Max 1100 //設置最大頂點數
#define Maxx(a,b) (a)>(b)?(a):(b)
#define Min(a,b) (a)<(b)?(a):(b)
int set[Max];
int indu[Max]; // 頂點入度
bool flag[Max]; //標記頂點是否在圖中
int a,b;
int find(int x){ //查+路徑壓縮
int j=x;
while(set[x]!=x)
x=set[x];
int temp;
while(j!=x){
temp=set[j];
set[j]=x;
j=temp;
}
return x;
}
int main(){
int Case=1;
while(scanf("%d%d",&a,&b)){
if(a<0 && b<0) //若a,b均小於0,則退出
break;
for(int i=1;i<Max;i++) //初始化
set[i]=i;
memset(flag,0,sizeof(flag));//初始化爲均不再圖中
memset(indu,0,sizeof(indu)); // 初始化圖中頂點的入度均爲0
bool trag=true; //標記圖中是否存在迴路(假設爲無向圖)
while(a!=0 && b!=0){
if(trag){ //若目前還不存在迴路
int x=find(a),y=find(b); //查父親節點
if(x==y) // 若相同,則說明存在迴路(這裏爲無向圖迴路)
trag=false;
else{ //若不相同
set[Maxx(x,y)]=Min(x,y); //大並小
flag[a]=flag[b]=true; //設置標記爲在圖中
indu[b]++;//入度增加
}
}
scanf("%d%d",&a,&b);
}
if(!trag) //若存在迴路
printf("Case %d is not a tree.\n",Case++);
else{ //不存在迴路
int i,num=0;
for(i=1;i<Max;i++) //判斷在圖中的頂點的入度是否滿足上述的兩個充分必要條件
if(flag[i]){
if(indu[i]>1)
break;
else if(indu[i]==0){
num++;
if(num>1)
break;
}
}
if(i<Max) //若不滿足
printf("Case %d is not a tree.\n",Case++);
else //滿足
printf("Case %d is a tree.\n",Case++);
}
}
return 0;
}