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, 终点处入度减出度为1。
代码:
/*hdoj 1116 并查集+欧拉通/回路*/
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define M 1005
int out[26], in[26], fat[26];
bool vis[26];
char s[M];
int f(int x){
if(x != fat[x]) fat[x] = f(fat[x]);
return fat[x];
}
void merge(int x, int y){
int a = f(x);
int b = f(y);
if(a != b) fat[a] = b;
}
int main(){
int n, t, i;
scanf("%d", &t);
while(t --){
memset(vis, 0, sizeof(vis));
memset(out, 0, sizeof(out));
memset(in, 0, sizeof(in));
scanf("%d", &n);
for(i = 0; i < 26; i ++) fat[i] = i;
for(i = 0; i < n; i ++){
scanf("%s", s);
int x = s[0]-'a';
int y = s[strlen(s)-1]-'a';
merge(x, y);
++out[x]; ++in[y];
vis[x] = vis[y] = 1;
}
int flag1 = 0;
for(i = 0; i < 26; i ++){ //判断是否联连通
if(vis[i]&&fat[i] == i) ++flag1;
}
if(flag1 > 1){
printf("The door cannot be opened.\n"); continue;
}
int flag2, flag3; //flag1是判断是否是全部出入度都相等,flag2是判读起始点有几个,flag3是终点有几个
flag1 = flag2 = flag3 = 0;
for(i = 0; i < 26; i ++){
if(vis[i]&&out[i] != in[i]){
++flag1;
if(out[i]-in[i] == 1) ++flag2;
if(in[i] - out[i] == 1) ++flag3;
}
}
if(flag1 == 0) printf("Ordering is possible.\n");
else if(flag1 == 2&&flag2 == 1&&flag3 == 1) printf("Ordering is possible.\n");
else printf("The door cannot be opened.\n");
}
return 0;
}
hdoj 1116 Play on Words 【并查集】+【欧拉路】
原文地址:http://blog.csdn.net/shengweisong/article/details/41098315