2013-12-11 07:51:46Morris

[UVA] 10441 - Catenyms

Problem C: Catenyms

A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the first letter of the second. For example, the following are catenyms:
dog.gopher
gopher.rat
rat.tiger
aloha.aloha
arachnid.dog
A compound catenym is a sequence of three or more words separated by periods such that each adjacent pair of words forms a catenym. For example,
aloha.aloha.arachnid.dog.gopher.rat.tiger
Given a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once. The first line of standard input contains t, the number of test cases. Each test case begins with 3 <= n <= 1000 - the number of words in the dictionary. n distinct dictionary words follow; each word is a string of between 1 and 20 lowercase letters on a line by itself. For each test case, output a line giving the lexicographically least compound catenym that contains each dictionary word exactly once. Output "***" if there is no solution.

Sample Input

2
6
aloha
arachnid
dog
gopher
rat
tiger
3
oak
maple
elm

Output for Sample Input

aloha.arachnid.dog.gopher.rat.tiger
***

題目描述:

找一條字典順序最小的,且每個單詞恰好經過一次。
題目解法:
用 dfs 找尤拉路徑或尤拉環道。

#include <stdio.h>
#include <string.h>
#include <map>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
struct edge {
    int to, e, used;
    edge(int a=0, int b=0, int c=0):
        to(a), e(b), used(c) {
        }
};
vector<edge> g[26];
vector<int> path;
int indeg[26], outdeg[26];
void dfs(int nd) {
    int i;
    for(i = 0; i < g[nd].size(); i++) {
        edge &e = g[nd][i];
        if(e.used == 0) {
            e.used = 1;
            dfs(e.to);
            path.push_back(e.e);
        }
    }
}
string dictionary[1005];
char s[1005][105];
int main() {
    int testcase, n;
    int i, j, k;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%d", &n);
        memset(indeg, 0, sizeof(indeg));
        memset(outdeg, 0, sizeof(outdeg));
        path.clear();
        for(i = 0; i < 26; i++)
            g[i].clear();
        for(i = 0; i < n; i++) {
            cin >> dictionary[i];
        }
        sort(dictionary, dictionary+n);
        for(i = 0; i < n; i++) {
            int len = dictionary[i].length();
            int x = dictionary[i][0] - 'a';
            int y = dictionary[i][len-1] - 'a';
            outdeg[x]++, indeg[y]++;
            g[x].push_back(edge(y, i, 0));
        }
        int a = 0, b = 0, c = 0;
        for(i = 0; i < 26; i++) {
            if(indeg[i] == outdeg[i]-1)
                a++;
            else if(indeg[i] == outdeg[i]+1)
                b++;
            else if(indeg[i] != outdeg[i])
                c++;
        }
        if(c) {
            puts("***");
            continue;
        }
        int rflag = 0;
        for(i = 0; i < 26; i++) {
            if(indeg[i] == outdeg[i]-1) {
                dfs(i);
                rflag = 1;
                break;
            }
        }
        if(rflag == 0) {
            for(i = 0; i < 26; i++) {
                if(outdeg[i]) {
                    dfs(i);
                    break;
                }
            }
        }
        if(path.size() != n )
            puts("***");
        else {
            for(i = path.size()-1; i >= 0; i--) {
                int idx = path[i];
                cout << dictionary[idx];
                if(i)    putchar('.');
            }
            puts("");
        }
    }
    return 0;
}