地址:
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 <string.h>
#include <memory.h>
#define OUT 10
typedef struct
{
int parent;
int height;
}Node;
Node set[26];
bool visited[26];
int record[26], num_record;
void Init()
{
int i;
for(i = 0; i < 26; i++)
{
visited[i] = false;
set[i].parent = i;
set[i].height = 1;
}
num_record = 0;
}
int Find(int x)
{
while(x != set[x].parent)
{
x = set[x].parent;
}
return x;
}
void Merge(int x, int y)
{
if(x == y)
{
return;
}
if(set[x].height == set[y].height)
{
set[y].parent = x;
set[x].height++;
}
else if(set[x].height > set[y].height)
set[y].parent = x;
else
set[x].parent = y;
}
int main()
{
int T, N;
int i, j;
char word[1005];
int letter[26];
int front, behind;
int a, b;
bool flag;
scanf("%d", &T);
for(i = 0; i < T; i++)
{
front = behind = 0;
memset(letter, 0, sizeof(letter));
Init();
scanf("%d", &N);
for(j = 0; j < N; j++)
{
scanf("%s", word);
a = word[0] - 'a';
b = word[strlen(word) - 1] - 'a';
letter[a]++;
letter[b]--;
Merge(Find(a), Find(b));
if(visited[a] == false)
{
visited[a] = true;
record[num_record++] = a;
}
if(visited[b] == false)
{
visited[b] = true;
record[num_record++] = b;
}
}
flag = false;
a = Find(record[0]);
for(j = 1; j < num_record; j++)
{
if(a != Find(record[j]))
{
flag = true;
break;
}
}
if(flag == true)
{
printf("The door cannot be opened.\n");
continue;
}
for(j = 0; j < 26; j++)
{
if(letter[j] > 1 || letter[j] < -1)
{
front = behind = OUT;
break;
}
else if(letter[j] == 1)
front++;
else if(letter[j] == -1)
behind++;
}
if((front == 1 && behind == 1) || (front == 0 && behind == 0))
{
printf("Ordering is possible.\n");
}
else
{
printf("The door cannot be opened.\n");
}
}
return 0;
}