Uva - 10129 - Play on Words


把单词收尾字母当作每条边的起点和终点,就抽象为一个有向图,判断有向图是否存在欧拉路。用到图论的知识,有向图最多只能有两个点的入度不等于出度,而且起点必须是出度恰好比入度大1,终点入度比出度大1,并且有向图的无向图是连通的。判断连通性用dfs方法判断。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <string>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <stack>
#include <queue>
#include <bitset> 
#include <cassert> 

using namespace std;

const int maxv = 26;
const int maxn = 1005;

int G[maxv][maxv];
int inDeg[maxv]; // 每个点的入度数
int outDeg[maxv]; // 每个点的出度数
int vis[maxv];

void dfs(int u)
{
	vis[u] = true;
	for (int i = 0; i < maxv; i++) {
		if (G[u][i] > 0) {
			G[u][i]--;
			G[i][u]--;
			dfs(i);
		}
	}
}

// 判断度数是否满足
bool okDeg()
{
	bool star = false;
	bool end = false;

	for (int i = 0; i < maxv; i++) {
		if (inDeg[i] != outDeg[i]) {
			if (!end && inDeg[i] == outDeg[i] + 1) { // 终点
				end = true;
			}
			else if (!star && inDeg[i] + 1 == outDeg[i]) { // 起点
				star = true;
			}
			else {
				return false;
			}
		}
	}
	return true;
}

bool okDfs()
{
	for (int u = 0; u < maxv; u++) {
		if (inDeg[u] + outDeg[u]) {
			if (vis[u] == false) {
				return false;
			}
		}
	}

	return true;
}

int main()
{
	ios::sync_with_stdio(false);
	int T;
	cin >> T;
	while (T--) {
		memset(G, 0, sizeof(G));
		memset(inDeg, 0, sizeof(inDeg));
		memset(outDeg, 0, sizeof(outDeg));
		memset(vis, 0, sizeof(vis));

		int edge, star;
		cin >> edge;
		while (edge--) {
			char ch[maxn];
			cin >> ch;
			int u = ch[0] - 'a';
			int v = ch[strlen(ch) - 1] - 'a';
			inDeg[u]++;
			outDeg[v]++;
			G[u][v]++;
			G[v][u]++;
			star = u;
		}

		dfs(star);
		if (okDfs() && okDeg()) {
			cout << "Ordering is possible.\n";
		}
		else {
			cout << "The door cannot be opened.\n";
		}
	}

	return 0;
}




posted @ 2015-06-17 14:54  Say舞步  阅读(183)  评论(0编辑  收藏  举报