码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 1386 Play on Words(有向欧拉通路 连通图)

时间:2014-11-13 00:20:11      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:style   http   io   color   ar   os   sp   for   strong   

每个单词可以看成首尾两个字母相连的一条边  然后就是输入m条边  判断能否构成有向欧拉通路了

有向图存在欧拉通路的充要条件:

 1. 有向图的基图连通;

 2. 所有点的出度和入度相等  或者  只有两个入度和出度不相等的点  且这两点入度与出度的差一个为-1(起点)一个为1(终点.

判断是否连通就是应用并查集了

 

[cpp] view plaincopybubuko.com,布布扣bubuko.com,布布扣
  1. #include<cstdio>  
  2. #include<cstring>  
  3. using namespace std;  
  4. const int N = 30, M = 100010;  
  5. struct edge{int u, v; } e[M];  
  6. int vis[N], in[N], out[N], par[N], m, ok;  
  7.   
  8. int Find(int x)  
  9. {  
  10.     int r = x, tmp;  
  11.     while(par[r] >= 0) r = par[r];  
  12.     while(x != r)  
  13.     {  
  14.         tmp = par[x];  
  15.         par[x] = r;  
  16.         x = tmp;  
  17.     }  
  18.     return r;  
  19. }  
  20.   
  21. void Union(int u, int v)  
  22. {  
  23.     int ru = Find(u), rv = Find(v), tmp = par[ru] + par[rv];  
  24.     if(par[ru] < par[rv]) par[rv] = ru, par[ru] = tmp;  
  25.     else par[ru] = rv, par[rv] = tmp;  
  26. }  
  27.   
  28. void connect()  
  29. {  
  30.     memset(par, -1, sizeof(par)); //初始化并查集  
  31.     for(int i = 0; i < m; ++i)  
  32.     {  
  33.         int u = e[i].u, v = e[i].v;  
  34.         if(Find(u) != Find(v)) Union(u, v);  
  35.     }  
  36.     for(int i = 0; i < 26; ++i)  
  37.         for(int j = 0; j < 26; ++j)  
  38.             if(vis[i] && vis[j] && Find(i) != Find(j)) ok = 0;  
  39. }  
  40.   
  41. int main()  
  42. {  
  43.     char s[1005];  
  44.     int u, v, cas;  
  45.     scanf("%d", &cas);  
  46.     while(cas--)  
  47.     {  
  48.         for(int i = 0; i < 26; ++i)  
  49.             vis[i] = in[i] = out[i] = 0;  
  50.         scanf("%d", &m);  
  51.         for(int i = 0; i < m; ++i)  
  52.         {  
  53.             scanf("%s", s);  
  54.             u = s[0] - ‘a‘, v = s[strlen(s) - 1] - ‘a‘;  
  55.             vis[u] = vis[v] = 1;  
  56.             e[i].u = u, e[i].v = v;  
  57.             ++in[u], ++out[v];  
  58.         }  
  59.   
  60.         int id = 0, od = 0;//i[d]记录入度比出度大1的点的个数 o[d]小1  
  61.         ok = 1;  
  62.         for(int i = 0; i < 26; ++i)  
  63.         {  
  64.             if(!vis[i]) continue;  
  65.             int k = in[i] - out[i];  
  66.             if(k < -1 || k > 1) {ok = 0; break;}  
  67.             if(k == 1) ++id;  
  68.             if(k == -1) ++od;  
  69.         }  
  70.         if(id > 1 || od > 1 || id - od) ok = 0;  
  71.         connect();  
  72.         if(ok)  printf("Ordering is possible.\n");  
  73.         else printf("The door cannot be opened.\n");  
  74.     }  
  75.     return 0;  
  76. }  

题目描述: 
有些秘门带有一个有趣的词迷。考古学家必须解开词迷才能打开门。由于没有其他方法可以 打开门,因此词迷就变得很重要。 每个门上有许多磁盘。每个盘上有一个单词,这些磁盘必须重新排列使得每个单词第一个字 母跟前一个单词后一个字母相同。例如单词"acm"可以跟在单词"motorola"的后面。你的任务是 编写一个程序,读入一组单词,然后判定是否可以经过重组使得每个单词第一个字母跟前一个单 词后一个字母相同,这样才能打开门。 

输入描述:

 输入文件中包含 T 个测试数据。输入文件的第一行就是 T,接下来是 T 个测试数据。每个测 试数据的第一行是一个整数 N,表示单词的个数(1≤N≤100000);接下来有 N行,每行是一个 单词;每个单词至少有 2个、至多有 1000 个小写字母,即单词中只可能出现字母‘a‘~‘z‘;在同一 个测试数据中,一个单词可能出现多次。 

输出描述: 

如果通过重组单词可以达到要求,输出"Ordering is possible.",否则输出"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.

POJ 1386 Play on Words(有向欧拉通路 连通图)

标签:style   http   io   color   ar   os   sp   for   strong   

原文地址:http://www.cnblogs.com/yuyanbian/p/4093824.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!