UVa10129 - Play on Words
题意:n个单词形成序列,能够使每一个单词的第一个字母和上一个单词的最后一个字母相同
分析:意即是否形成欧拉道路,所以先以每个单词的首、尾形成点,连成有向边构图。
形成欧拉道路有2个条件:
1.图连通
2.图中所有点的出度`等于`入度,或只有两个奇度点并且一个点的入度比出度大1(终点),另一个点的出度比入度大1(起点)。
对于1:dfs判之。2 统计出入度情况判之
#include <cstdio> #include <cstring> using namespace std; const int maxn = 100; int T, n, G[maxn][maxn], c[maxn], in[maxn], out[maxn]; int vis[maxn]; void dfs(int u) { vis[u] = 1; //访问标记 for (int v =0; v < 26; v++) //字母节点 if (!vis[v] && G[u][v]) dfs(v); //没有被访问并且有有向边 } int main() { char s[2000]; scanf("%d", &T); while (T--) { memset(vis, 1, sizeof(vis)); memset(G, 0, sizeof(G)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); scanf("%d", &n); for (int i =0; i < n; i++) { scanf("%s", s); int len = strlen(s); int r = s[0]-'a'; //首 int t = s[len-1] - 'a'; //尾 G[r][t] = 1; //有有向边 in[t]++;out[r]++; //很重要!!!,出入度别写反了, vis[r] = vis[t] = 0; //将其置为未访问状态 } int flag = 0; int p = 0, cnt1 = 0, cnt2 =0, cnt3 = 0; for (int i = 0; i < 26; i++) { if (out[i] == in[i]) continue; //环的情况 if (out[i] == in[i]+1) { cnt1++;p = i; //起始点 } else if (in[i] == out[i] + 1) cnt2++; //其余点 else cnt3++; //没有满足 } if (cnt3 > 0) { printf("The door cannot be opened.\n"); continue; }
// 环或者是 if (cnt1==1 &&cnt2 == 1 || cnt1==0 && cnt2==0) flag = 1; else flag = 0; dfs(p); for (int i = 0; i < 26; i++) if(!vis[i]) flag = 0; if (flag) printf("Ordering is possible.\n"); else printf("The door cannot be opened.\n"); } return 0; }
ps: 一些细节没注意,debug了很久,也参照了别人的代码,要加油!!!T^T。。。