poj1308

大致題目:給定若干條邊,邊爲有向邊<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;
}
						

 

發佈了209 篇原創文章 · 獲贊 20 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章