POJ-1386 Play on Words 有向图欧拉通路判定
题意:给定一系列的单词,这些单词要使用类似与成语接龙的方式将他们连接起来,现在问是否存在这样一个通路。
解法:为什么这种题目刚看起来总是像那个什么哈密顿回路呢?欧拉回路主要解决对边的遍历问题,因此我们需要将已知条件转移到边上的信息即可。对于一个单词acm,那么就连接一条从a到m的边,那么走这条边也就访问了这个单词。有向图判定是否存在欧拉路径的方法是:在保证图连通的情况下,所有点的入度等于出度或者是存在两个点,一个点入度比出度大1,另一个点出度比入度大1。
代码如下:
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> #include <vector> using namespace std; int set[30]; int N, odd, in[30], out[30]; int hav[30]; vector<int>v; int find(int x) { return set[x] = x == set[x] ? x : find(set[x]); } void merge(int a, int b) { set[a] = b; } int main() { int T, ok; char str[1005]; scanf("%d", &T); while (T--) { for(int i = 0; i < 26; ++i) { hav[i] = 0; set[i] = i; } v.clear(); scanf("%d", &N); ok = 0; memset(in, 0, sizeof (in)); memset(out, 0, sizeof (out)); for (int i = 0; i < N; ++i) { scanf("%s", str); char a = str[0]-'a', b = str[strlen(str)-1]-'a'; ++out[a]; ++in[b]; hav[a] = hav[b] = 1; merge(find(a), find(b)); } for (int i = 0; i < 26; ++i) { if (set[i] == i && hav[i]) { ++ok; } if (in[i] != out[i]) { v.push_back(i); } } if (ok != 1) { puts("The door cannot be opened."); continue; } if (v.size() > 2) { puts("The door cannot be opened."); } else if (v.size() == 2){ if ((in[v[0]]-out[v[0]])*(in[v[1]]-out[v[1]]) == -1) { puts("Ordering is possible."); } else { puts("The door cannot be opened."); } } else { puts("Ordering is possible."); } } return 0; }