您的位置:首页 > 其它

POJ 1386 Play on Words

2013-10-27 21:56 495 查看
欧拉回路

给出n个单词,如果一个单词的首字母和另一个单词的尾字母相同,则可以相连成一条边。用欧拉的思想做,把一个单词的首字母和尾字母作为一个顶点,如果满足条件,就连出一条有向边,记录出度和入度,用并查集来判断是否为一个强连通分支,如果是,再判断奇数度是否为2个或者0个。

AC代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#define max_len 1010
#define maxv 30

using namespace std;

int in[maxv];
int out[maxv];
int p[maxv];
bool used[maxv];

void init() {
for(int i = 0; i < maxv; ++i) {
in[i] = 0;
out[i] = 0;
p[i] = -1;
used[i] = 0;
}
}
int find_set(int x) {
if(0 <= p[x]) {
p[x] = find_set(p[x]);
return p[x];
}
return x;
}
void union_set(int a, int b) {
int r1 = find_set(a);
int r2 = find_set(b);
if(r1 == r2)
return;
int n1 = p[r1];
int n2 = p[r2];
if(n1 < n2) {
p[r2] = r1;
p[r1] += n2;
}
else {
p[r1] = r2;
p[r2] += n1;
}
}
int main() {
int t = 0;
char word[max_len];
scanf("%d", &t);
while(t--)
{
int n, i;
init();
scanf("%d", &n);
for(i = 0; i < n; ++i)
{
scanf("%s", word);
int len = strlen(word);
int s = word[0] - 'a';
int e = word[len - 1] - 'a';
used[s] = 1;
used[e] = 1;
out[s]++;
in[e]++;
union_set(s, e);
}

int scc = 0;
for(i = 0; i < maxv; ++i) {
if(used[i] && 0 > p[i])
++scc;
}
if(1 < scc) {
printf("The door cannot be opened.\n");
continue;
}
int a = 0;
int b = 0;
for(i = 0; i < maxv; ++i) {
if(used[i] && in[i] != out[i]) {
if(1 == (in[i] - out[i]))
++a;
else if(1 == (out[i] - in[i]))
++b;
else
break;
}
}
if(i < maxv)
printf("The door cannot be opened.\n");
else if(0 == (a + b) || (1 == a && 1 == b))
printf("Ordering is possible.\n");
else
printf("The door cannot be opened.\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: