地址:
http://acm.hit.edu.cn/judge/show.php?Proid=1033&Contestid=0思路:可以把这道题等价地看成有向图中求哈密顿路的问题,每个在单词首尾出现过的字母看作一个节点,每个单词首字母看作节点的出度加1,尾字母看作节点的入度加1,而形成哈密顿路的条件是除了哈密顿路首尾两个节点外,其他节点的出度等于入度,而首节点出度比入度多1,尾节点入度比出度多1。除此之外,还要考虑图的连通性问题,因为不连通的图是无法形成哈密顿路的,使用并查集来判断图是否连通。并查集的内容详情可见:
http://www.cppblog.com/amazon/archive/2009/08/15/93457.html代码如下:
 #include <stdio.h>
#include <stdio.h>
 #include <string.h>
#include <string.h>
 #include <memory.h>
#include <memory.h>

 #define OUT 10
#define OUT 10

 typedef struct
typedef struct  


 {
{
 int parent;
    int parent;
 int height;
    int height;
 }Node;
}Node;

 Node set[26];
Node set[26];
 bool visited[26];
bool visited[26];
 int record[26], num_record;
int record[26], num_record;

 void Init()
void Init()


 {
{
 int i;
    int i;

 for(i = 0; i < 26; i++)
    for(i = 0; i < 26; i++)

 
     {
{
 visited[i] = false;
        visited[i] = false;
 set[i].parent = i;
        set[i].parent = i;
 set[i].height = 1;
        set[i].height = 1;
 }
    }
 num_record = 0;
    num_record = 0;
 }
}

 int Find(int x)
int Find(int x)


 {
{
 while(x != set[x].parent)
    while(x != set[x].parent)

 
     {
{
 x = set[x].parent;
        x = set[x].parent;
 }
    }

 return x;
    return x;
 }
}

 void Merge(int x, int y)
void Merge(int x, int y)


 {
{
 if(x == y)
    if(x == y)

 
     {
{
 return;
        return;
 }
    }
 if(set[x].height == set[y].height)
    if(set[x].height == set[y].height)

 
     {
{
 set[y].parent = x;
        set[y].parent = x;
 set[x].height++;
        set[x].height++;
 }
    }
 else if(set[x].height > set[y].height)
    else if(set[x].height > set[y].height)
 set[y].parent = x;
        set[y].parent = x;
 else
    else
 set[x].parent = y;
        set[x].parent = y;
 }
}

 int main()
int main()


 {
{
 int T, N;
    int T, N;
 int i, j;
    int i, j;
 char word[1005];
    char word[1005];
 int letter[26];
    int letter[26];
 int front, behind;
    int front, behind;
 int a, b;
    int a, b;
 bool flag;
    bool flag;

 scanf("%d", &T);
    scanf("%d", &T);

 for(i = 0; i < T; i++)
    for(i = 0; i < T; i++)

 
     {
{
 front = behind = 0;
        front = behind = 0;
 memset(letter, 0, sizeof(letter));
        memset(letter, 0, sizeof(letter));
 Init();
        Init();

 scanf("%d", &N);
        scanf("%d", &N);

 for(j = 0; j < N; j++)
        for(j = 0; j < N; j++)

 
         {
{
 scanf("%s", word);
            scanf("%s", word);
 a = word[0] - 'a';
            a = word[0] - 'a';
 b = word[strlen(word) - 1] - 'a';
            b = word[strlen(word) - 1] - 'a';
 letter[a]++;
            letter[a]++;
 letter[b]--;
            letter[b]--;
 Merge(Find(a), Find(b));
            Merge(Find(a), Find(b));
 if(visited[a] == false)
            if(visited[a] == false)

 
             {
{
 visited[a] = true;
                visited[a] = true;
 record[num_record++] = a;
                record[num_record++] = a;
 }
            }
 if(visited[b] == false)
            if(visited[b] == false)

 
             {
{
 visited[b] = true;
                visited[b] = true;
 record[num_record++] = b;
                record[num_record++] = b;
 }
            }

 }
        }

 flag = false;
        flag = false;
 a = Find(record[0]);
        a = Find(record[0]);
 for(j = 1; j < num_record; j++)
        for(j = 1; j < num_record; j++)

 
         {
{
 if(a != Find(record[j]))
            if(a != Find(record[j]))

 
             {
{
 flag = true;
                flag = true;
 break;
                break;
 }
            }
 }
        }
 if(flag == true)
        if(flag == true)

 
         {
{
 printf("The door cannot be opened.\n");
            printf("The door cannot be opened.\n");
 continue;
            continue;
 }
        }
 
        
 for(j = 0; j < 26; j++)
        for(j = 0; j < 26; j++)

 
         {
{
 if(letter[j] > 1 || letter[j] < -1)
            if(letter[j] > 1 || letter[j] < -1)

 
             {
{
 front = behind = OUT;
                front = behind = OUT;
 break;
                break;
 }
            }
 else if(letter[j] == 1)
            else if(letter[j] == 1)
 front++;
                front++;
 else if(letter[j] == -1)
            else if(letter[j] == -1)
 behind++;
                behind++;
 }
        }

 if((front == 1 && behind == 1) || (front == 0 && behind == 0))
        if((front == 1 && behind == 1) || (front == 0 && behind == 0))

 
         {
{
 printf("Ordering is possible.\n");
            printf("Ordering is possible.\n");
 }
        }
 else
        else

 
         {
{
 printf("The door cannot be opened.\n");
            printf("The door cannot be opened.\n");
 }
        }
 }
    }

 return 0;
    return 0;
 }
}