ACM: 有向欧拉图 图论题 poj 1386 …

来源:互联网 发布:网络安全工程师年薪 编辑:程序博客网 时间:2024/05/21 22:34
                                     Play on Words
Description
Some of the secret doors containa very interesting word puzzle. The team of archaeologists has tosolve it to open that doors. Because there is no other way to openthe doors, the puzzle is very important for us.

There is a large number of magnetic plates on every door. Everyplate has one word written on it. The plates must be arranged intoa sequence in such a way that every word begins with the sameletter as the previous word ends. For example, the word ``acm'' canbe followed by the word ``motorola''. Your task is to write acomputer program that will read the list of words and determinewhether it is possible to arrange all of the plates in a sequence(according to the given rule) and consequently to open thedoor.

Input

The input consists of T testcases. The number of them (T) is given on the first line of theinput file. Each test case begins with a line containing a singleinteger number Nthat indicates the number of plates (1<= N <= 100000). Then exactly Nlinesfollow, each containing a single word. Each word contains at leasttwo and at most 1000 lowercase characters, that means only letters'a' through 'z' will appear in the word. The same word may appearseveral times in the list.

Output

Your program has to determinewhether it is possible to arrange all the plates in a sequence suchthat the first letter of each word is equal to the last letter ofthe previous word. All the plates from the list must be used, eachexactly once. The words mentioned several times must be used thatnumber of times.
If there exists such an ordering of plates, your program shouldprint the sentence "Ordering is possible.". Otherwise, output thesentence "The door cannot be opened.".

Sample Input

3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok

Sample Output

The door cannot be opened.
Ordering is possible.
The door cannot be opened.

 

题意: 单词连接, 每个单词的最后一个字母是下一个单词的开头, 表示这两个单词连通, 现在要你判断全部

     单词是否连通.

解题思路:

         1. 图论题. 有向欧拉图 + 并查集.

     有向图中的欧拉图判定条件:

           (1) 所有的点联通
            (2)欧拉回路中所有点的入度和出度一样.
            (3)欧拉通路中终点的入度- 出度 = 1,起点的 初度 - 入度 = 1, 其他的所有点入度 = 出度;

 

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
#define MAXN 100005
#define MAX 30

int n;
char str[MAXN];
int indu[MAX], outdu[MAX];
int p[MAX*MAX], leg[MAX];
bool vis[MAX];

inline int getIndex(char ch)
{
 return (int)(ch-'a');
}

void init()
{
 memset(indu,0,sizeof(indu));
 memset(outdu,0,sizeof(outdu));
 memset(vis,false,sizeof(vis));
 for(int i = 0; i < 26; ++i)
  p[i] = i;
}

int find(int x)
{
 return p[x] == x ? x : (p[x] = find(p[x]));
}

int union_set(int x,int y)
{
 x = find(x);
 y = find(y);
 if(x == y) return 1;
 else p[y] = x;
 return 0;
}

int main()
{
// freopen("input.txt","r",stdin);
 int caseNum;
 scanf("%d",&caseNum);
 int i, j;
 while(caseNum--)
 {
  scanf("%d",&n);
  init();
  for(i = 0; i <n; ++i)
  {
   scanf("%s",str);
   int t1 =getIndex(str[0]);
   int t2 =getIndex(str[strlen(str)-1]);
   indu[t1]++;
   outdu[t2]++;
   vis[t1] =vis[t2] = 1;
   union_set(t1,t2);
  }

  for(i = 0; i< 26; ++i)
   p[i] =find(i);

  int flag = 0;
  for(i = 0; i <26; ++i)
  {
   if(i == p[i]&& vis[i])
    flag++;
  }
  if(flag >1)
  {
   printf("Thedoor cannot be opened.\n");
   continue;
  }

  j = 0;
  for(i = 0; i <26; ++i)
  {
   if(vis[i]&& indu[i] != outdu[i])
    leg[j++]= i;
  }

  if(j == 0)
  {
   printf("Orderingis possible.\n");
   continue;
  }
  else
  {
   if(j == 2&& ( (outdu[leg[0]] - indu[leg[0]]== 1 && indu[leg[1]] -outdu[leg[1]] == 1)
      ||(outdu[leg[1]] - indu[leg[1]] == 1&& indu[leg[0]] - outdu[leg[0]] ==1) ))
   {
    printf("Orderingis possible.\n");
   }
   else
    printf("Thedoor cannot be opened.\n");
  }
 }
 return 0;
}

0 0
原创粉丝点击