poj 2337 Catenyms(および+dfs+Eulerループを調べる)


Catenyms
Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)
Total Submission(s) : 6   Accepted Submission(s) : 5
Problem Description
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 last 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.
 
Input
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.
 
Output
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

 
 
Sample Output

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

 
         n個の単語を入力して、すべての単語はすべて1本のその単語の頭文字から尾文字の辺を形成して、単語の尾文字は次の単語の頭文字と同じで、もしこのような道を構成することができるならば、つまりこのような1本のつながっている単語の列を構成することができて、出力の経路(単語列)、もし複数のならば、辞書の順序で出力して、道が見つからないならば***を出力します.
         この問題は長い間やっていましたね.主に辺の部分を建てて、長い間見ていましたが、隣接行列を使うことができませんでした.それからチェーンテーブルを使って、出力経路という難しいことをしました.それから他の人のコードを参考にしてみると、そのdfs経路がこんなに巧妙であることに気づきました.実に巧みだ.
リンク:http://poj.org/problem?id=2337
コード:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;

bool app[30];
char res[1005][26];
int in[30], out[30], deg[30], father[30], adj[30];
int n, ant, odd, begin, end;

struct edge
{
    bool vis;
    char sh[25];
    int y, next;
}a[1005];

bool cmp(edge a, edge b)
{
    return strcmp(a.sh, b.sh) > 0;
}

void init()
{
    int i;
    ant = odd = 0;
    memset(app, false, sizeof(app));
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    memset(deg, 0, sizeof(deg));
    memset(adj, -1, sizeof(adj));
    for(i = 0; i < 1005; i++) a[i].vis = false;
    for(i = 0; i < 26; i++) father[i] = i;
}

int find(int x)
{
    if(x != father[x])
    {
        father[x] = find(father[x]);
    }
    return father[x];
}

void Union(int x, int y)
{
    father[x] = y;
}

int judge()     //        。0   ,1    ,2   
{
    int i, k;
    for(i = 0; i < 26; i++)     //       
    {
        if(!app[i]) continue;
        deg[i] = in[i] - out[i];
        if(abs(deg[i]) > 1) return 0;
        if(deg[i] > 0) begin = i;   //  
        if(deg[i] < 0) end = i;     //  
        if(deg[i]%2) odd++;
        if(odd > 2) return 0;
    }
    for(i = 0; i < 26; i++) if(app[i]) break;
    k = find(i);
    for(i = k+1; i < 26; i++)   //     
    {
        if(!app[i]) continue;
        if(k != find(i)) return 0;
    }
    if(odd == 0)    //     
    {
        for(i = 0; i < 26; i++)
            if(app[i]) break;
        begin = i;
        return 1;
    }
    return 2;
}

void dfs(int x, int id) //        ,   !!!
{
    int i;
	for(i = adj[x]; i != -1; i = a[i].next)
	{
		if(!a[i].vis)
		{
			a[i].vis = true;
			dfs(a[i].y, i);
		}
	}
	if(id != -1) strcpy(res[ant++], a[id].sh);  //          
}

int main()
{
    int i, x, y, fx, fy, t, len, tar;
    scanf("%d", &t);
    while(t--)
    {
        init();
        scanf("%d", &n);
        for(i = 0; i < n; i++)
        {
            scanf("%s", a[i].sh);
        }
        //         ,         ,          
        sort(a, a+n, cmp);  //         ,          
        for(i = 0; i < n; i++)
        {
            len = strlen(a[i].sh);
            x = a[i].sh[0] - 'a';
            y = a[i].sh[len-1] - 'a';
            in[x]++;
            out[y]++;
            app[x] = true;
            app[y] = true;
            /// *****  *****
            a[i].y = y;
            a[i].next = adj[x];
            adj[x] = i;
            /// ***************
            fx = find(x);
            fy = find(y);
            if(fx != fy) Union(fx, fy);
        }
        tar = judge();
        if(tar == 0)
        {
            printf("***
"); continue; } dfs(begin, -1); printf("%s", res[ant-1]); for(i = ant-2; i >= 0; i--) { printf(".%s", res[i]); } printf("
"); } return 0; }