zoj 2016 Play on Words 欧拉回路

来源:互联网 发布:各大编程语言效率比较 编辑:程序博客网 时间:2024/05/01 12:29

题目大意:给出一些单词,问能否摆成类似成语接龙的顺序(即前一个单词的最后一个字母要和下一个单词首字母相同)。

对于每个单词,只有首尾两字母重要,该单词可看做由首字母到尾字母的一条边,即所有单词的首尾两字母看做图中节点,每个单词可看做一条边,构造好有向图后,若要摆成题意要求的顺序,即判断是否存在欧拉回路即可。

#include <stdio.h>#include <string.h>int t,n;char word[1001];//存储每个单词int od[30],id[30];//每个顶点的出度和入度int bused[30],p[30];//bused表示该顶点是否存在,p是并查集中的父节点struct edge{int u,v;}edges[100010];void init(){int i;for(i=0;i<26;i++)p[i]=i;}int get(int x){if(p[x]==x)return x;elsereturn p[x]=get(p[x]);}bool con(){int u,v,i;init();for(i=0;i<n;i++){u=edges[i].u;v=edges[i].v;u=get(u);v=get(v);if(u!=v)p[u]=v;}int sum=0;for(i=0;i<26;i++){if(bused[i]==0)continue;if(p[i]==i)sum++;}if(sum>1)return false;elsereturn true;}int main(){int u,v;int i,j;scanf("%d",&t);for(i=0;i<t;i++){memset(bused,0,sizeof(bused));memset(od,0,sizeof(od));memset(id,0,sizeof(id));scanf("%d",&n);for(j=0;j<n;j++){scanf("%s",word);u=word[0]-'a';v=word[strlen(word)-1]-'a';od[u]++;id[v]++;bused[u]=bused[v]=1;edges[j].u=u;edges[j].v=v;}bool euler=true;int one=0;int none=0;for(j=0;j<26;j++){if(bused[j]==0)continue;if(od[j]-id[j]>1||id[j]-od[j]>1) {euler=false;break;}if(od[j]-id[j]==1){one++;if(one>1) {euler=false;break;}}if(id[j]-od[j]==1){none++;if(none>1) {euler=false;break;}}}if(one!=none)euler=false;if(!con()) euler=false;if(euler) printf("Ordering is possible.\n");else printf("The door cannot be opened.\n");}return 0;}


 

原创粉丝点击