UVa 10129 单词 (欧拉通路)

题意:

输入n(n≤100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同(例如acm、malform、mouse)。每个单词最

多包含1000个小写字母。输入中可以有重复单词。

分析:

可以看出, 把字母看成顶点(最多26个), 然后单词就是有向边, 单词与单词之间的关系就连接起来了, 然后建立邻接矩阵, 自环的可以忽略, 记录输入的字母有哪几个, 字母的度数。

然后图中存在欧拉通路的条件有2个

(1) 连通(我用了dfs来判断)

(2) 要么没有奇度顶点, 如果有, 那么肯定是有一个入度-出度=1 有一个入度-出度= -1。

用好这两个条件就可以判定应该就可以得出答案了

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int degree[26],used[26];//度数   有没有使用过
 4 int G[26][26];// 邻接矩阵
 5 int n;
 6 int id(int a){
 7     return a-'a';
 8 }
 9 int vis[26];
10 void dfs(int u){
11     vis[u] = 1;
12     for(int i = 0; i < 26; i++){
13         if(G[u][i] && !vis[i]){
14             dfs(i);
15         }
16     }
17 }
18 
19 bool judge(){
20     int num1 = 0, num2 = 0;
21     int u = 0, v;
22     for(int i = 0; i< 26; i++){
23         if(used[i]){
24             u = i;//u一开始等于图中任意一个顶点
25             break;
26         }
27     }
28     for(int i = 0; i < 26; i++){
29         if(used[i]){
30             if(degree[i] != 0){
31                 if(degree[i] == 1) {num1++; u = i;}//此时u就要等于入度>出度的顶点了
32                 else if(degree[i] == -1){num2++; v = i;}
33                 else return false;
34             }
35         }
36     }
37     if((num1 || num2) && num1 + num2 != 2) return false;//如果有 而且不是只有2个 就可以判为false了
38 
39     memset(vis,0,sizeof(vis));
40     dfs(u);
41     for(int i = 0; i < 26; i++){
42         if(used[i] && !vis[i]){//如果有这个点, 遍历又没遍历到 false;
43             return false;
44         }
45     }
46     return true;
47 
48 }
49 int main(){
50     int T;
51     scanf("%d", &T);
52     while(T--){
53         memset(degree,0,sizeof(degree));
54         memset(used,0,sizeof(used));
55         memset(G,0,sizeof(G));
56         scanf("%d", &n);
57         for(int i = 0; i < n; i++){
58             char s[1007];
59             scanf("%s", s);
60             int s1 = s[0] , s2 = s[strlen(s)-1];
61             if(s1 != s2){
62                 G[id(s1)][id(s2)] = 1;
63             }
64             used[s1 -'a'] = 1;
65             used[s2 -'a'] = 1;
66             degree[id(s1)]++;//出度++
67             degree[id(s2)]--;//入度--
68         }
69 //        for(int i = 0; i<26; i++){//观察度数
70 //            if(used[i])
71 //                printf("%c %d\n", i+'a', degree[i]);
72 //        }
73         printf("%s\n", judge()? "Ordering is possible.":"The door cannot be opened.");
74     }
75 }

 

posted @ 2017-07-20 11:27  Neord  阅读(285)  评论(0编辑  收藏  举报