一本通1528单词游戏
欧拉回路和欧拉路径的几个概念:
欧拉环:图中经过每条边一次且仅一次的环;
欧拉路径:图中经过每条边一次且仅一次的路径;
欧拉图:有至少一个欧拉环的图;
半欧拉图:没有欧拉环,但有至少一条欧拉路径的图。
【无向图】
一个无向图是欧拉图当且仅当该图是连通的(注意,不考虑图中度为0的点,因为它们的存在对于图中是否存在欧拉环、欧拉路径没有影响)且所有点的度数都是偶数;一个无向图是半欧拉图当且仅当该图是连通的且有且只有2个点的度数是奇数(此时这两个点只能作为欧拉路径的起点和终点);
证明:因为任意一个点,欧拉环(或欧拉路径)从它这里进去多少次就要出来多少次,故(进去的次数+出来的次数)为偶数,又因为(进去的次数+出来的次数)=该点的度数(根据定义),所以该点的度数为偶数。
【有向图】
一个有向图是欧拉图当且仅当该图的基图(将所有有向边变为无向边后形成的无向图,这里同样不考虑度数为0的点)是连通的且所有点的入度等于出度;一个有向图是半欧拉图当且仅当该图的基图是连通的且有且只有一个点的入度比出度少1(作为欧拉路径的起点),有且只有一个点的入度比出度多1(作为终点),其余点的入度等于出度。
证明:与无向图证明类似,一个点进去多少次就要出来多少次。
----------------------------------下面是题目-------------------------------
单词游戏
题目描述
来自 ICPC CERC 1999/2000,有改动。
有 N 个盘子,每个盘子上写着一个仅由小写字母组成的英文单词。你需要给这些盘子安排一个合适的顺序,使得相邻两个盘子中,前一个盘子上单词的末字母等于后一个盘子上单词的首字母。请你编写一个程序,判断是否能达到这一要求。如果能,请给出一个合适的顺序。
输入格式
多组数据。第一行给出数据组数 T,每组数据第一行给出盘子数量 N,接下去 N 行给出小写字母字符串,一种字符串可能出现多次。
输出格式
若存在一组合法解输出Ordering is possible.
,否则输出The door cannot be opened.
。
样例
样例输入
3
2
acm
ibm
3
acm
malform
mouse
2
ok
ok
样例输出
The door cannot be opened.
Ordering is possible.
The door cannot be opened.
数据范围与提示
1≤N≤105,∣S∣≤1000
sol:
判断是否存在欧拉路径或欧拉图,用并查集判断连通性,然后入度出度判断一下
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=30,M=200005; 4 int T,n; 5 int Indeg[N],Outdeg[N]; 6 int Father[N]; 7 inline int Get_Father(int x) 8 { 9 return (Father[x]==x)?(x):(Father[x]=Get_Father(Father[x])); 10 } 11 inline void Print(int opt) 12 { 13 if(opt==1) 14 { 15 puts("The door cannot be opened."); 16 } 17 else 18 { 19 puts("Ordering is possible."); 20 } 21 return; 22 } 23 char S[M>>1]; 24 int main() 25 { 26 // freopen("words.in","r",stdin); 27 // freopen("my.out","w",stdout); 28 int i; 29 scanf("%d",&T); 30 while(T--) 31 { 32 memset(Indeg,0,sizeof Indeg); 33 memset(Outdeg,0,sizeof Outdeg); 34 for(i=1;i<=26;i++) 35 { 36 Father[i]=i; 37 } 38 scanf("%d",&n); 39 for(i=1;i<=n;i++) 40 { 41 scanf("%s",S+1); 42 int Len=strlen(S+1); 43 int x=S[1]-'a'+1,y=S[Len]-'a'+1; 44 Indeg[y]++; 45 Outdeg[x]++; 46 Father[Get_Father(x)]=Get_Father(y); 47 } 48 int cnt=0; 49 bool Flag=0; 50 for(i=1;i<=26;i++) if(abs(Indeg[i]-Outdeg[i])>1) 51 { 52 Flag=1; break; 53 } 54 if(Flag) 55 { 56 Print(1); 57 continue; 58 } 59 for(i=1;i<=26;i++) 60 if((Indeg[i]||Outdeg[i])&&Get_Father(i)==i) 61 { 62 if((++cnt)>1) break; 63 } 64 if(cnt>1) 65 { 66 Print(1); 67 continue; 68 } 69 int cnt1=0,cnt2=0; 70 for(i=1;i<=26;i++) 71 { 72 if(Indeg[i]>Outdeg[i]) cnt1++; 73 else if(Indeg[i]<Outdeg[i]) cnt2++; 74 } 75 if((cnt1!=cnt2)||(cnt1>1)||(cnt2>1)) 76 { 77 Print(1); 78 } 79 else 80 { 81 Print(2); 82 } 83 } 84 return 0; 85 } 86 /* 87 input 88 4 89 2 90 acm 91 ibm 92 3 93 acm 94 malform 95 mouse 96 2 97 ok 98 ok 99 4 100 abc 101 cba 102 abc 103 abc 104 output 105 The door cannot be opened. 106 Ordering is possible. 107 The door cannot be opened. 108 The door cannot be opened. 109 */