Uva 10129 (dfs判斷連通 +歐拉回路)


傳送門!!!!!!!!----->點擊打開題目鏈接

題意:輸入一個n代表有n個單詞,接下來輸入n個單詞,問是否可以把所有的單詞排成一個序列,使得每個單詞的第一個字母和上一個單詞的最后一個字母相同。

思路:把字母看成節點,單詞看成有向邊,建圖。當且僅當途中存在歐拉路徑時題目敘述成立。

歐拉回路:能否從無向圖中的一個節點出發走出一條道路,每條邊恰好經過一次,。如果可以,則這樣的路線稱為歐拉道路。

歐拉道路的定理:最多只能有兩個點的度入度和出度不相等,而且必須是其中一個點的出度比入度大1(把他作為起點),另一個的入度比出度大一(作為終點)。並且圖是連通的。

所以這道題的思路就是判定建出來的圖是否存在歐拉回路。所以需要證明兩步,第一步是證明這個圖是連通的,第二部是證明最多存在兩個點入度和出度的不相等,且一個出度比入度大一,一個入度比出度大一。

詳情看代碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 30;
int vis[maxn]; //標記數組,用來標記該點是否聯通。 
int son,far;
int in[maxn]; // 統計某個點的入度 
int out[maxn]; //統計某個點的出度 
int [maxn][maxn]; // 圖 

void dfs(int u){      // 判斷是否為連通圖  
	vis[u] = 1;
	for(int i = 0 ; i < maxn ; i ++){
		if(G[u][i] && !vis[i])
		dfs(i);
	}
}
int main(){
	string str;
	int kase;
	cin >> kase ;
	while(kase --){
		int n ,cnt = 0,n_in = 0,n_out = 0, start= 0;
		cin >> n;
		memset(in,0,sizeof(in));
		memset(out,0,sizeof(out));
		memset(G,0,sizeof(G));
		memset(vis,0,sizeof(vis));
		for(int i = 0 ; i < n ; i ++){ // 建圖 
			cin >> str;
			far = str[0] - 'a';
			son = str[str.size() - 1] - 'a' ;
			out[far] ++;
			in[son] ++;
			G[far][son] = 1;
		}
		for(int i = 0 ; i < 27 ; i++){  // 統計點的入度和出度 
			if(in[i] != out[i]){  //當入度和出度不相等時 
				if(in[i] == out[i] + 1)
					n_in ++;
				else if(in[i] + 1 == out[i]) 
					n_out ++,start = i ; 
				else n_in += maxn;
			}
			if(start = 0 && in[i] == out[i])  // 當所有點入度和出度 都相等的時候,任何一個點都可以作為起點。 
				start = i;
		}
		int ok = 0;
		if((n_in == 1 && n_out == 1) || (n_in == 0 && n_out ==0)){  //判斷條件2是否成立 
			dfs(start);
			ok = 1;
		}
			
		for(int i = 0 ; i < 27 ; i++) //判斷條件1是否成立 當這點存在但是不連通時 cnt++; 
			if(vis[i] == 0 && (in[i]||out[i]))
				cnt ++;
		if(cnt == 0 &&ok == 1)
			cout <<"Ordering is possible." <<endl;
		else 
			cout << "The door cannot be opened." <<endl; 
	}
	return 0;
}



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com