POJ1386 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;    
}
原文地址:https://www.cnblogs.com/Lyush/p/2983520.html