POJ 1386 (欧拉路径+并查集)

来源:互联网 发布:阿里云服务器公网ip 编辑:程序博客网 时间:2024/05/22 04:35

题目的大意是:给出一些单词,问能否拼接成一串,使单词字母首尾相连。
例如,Sample中的:
acm
malform
mouse
我们可以构造出:
acm->malform->mouse,符合题目要求。

/*1. 有向图G为欧拉图,当且仅当G的基图 连通,且所有顶点的入度等于出度。2. 有向图G为半欧拉图,当且仅当G的基图连通,且存在一个顶点的入度比出度大1,   一个顶点入度比出度小1,其它所有顶点的入度等于出度。3. 无向图G为欧拉图,当且仅当G为连通的,且所有顶点度为偶数或者度为奇数的顶点个数为0或者24. 图的连通性可用并查集判断*/#include <iostream>using namespace std;const int MAX_LEN = 1002;const int ALPHA_NUM = 26;int degree[ALPHA_NUM], father[ALPHA_NUM];char word[MAX_LEN];int find_set(int i){if (i != father[i]){father[i] = find_set(father[i]);}return father[i];// while (i != father[i]){// i = father[i];// }// return father[i];}void make_set(int i){if (-1 == father[i]) father[i] = i;}void union_set(int a, int b){a = find_set(a);b = find_set(b);if (a != b){father[a] = b;// if (rank[a] == rank[b]){// father[a] = b;// rank[a]++;// }// else if (rank[a] < rank[b]){// father[a] = b;// }// else{// father[b] = a;// }}}int main(){int c, n, i, j, len;scanf("%d", &c);for (i = 0; i < c; ++i){memset(degree, 0, sizeof(degree));memset(father, -1, sizeof(father));scanf("%d", &n);for (j = 0; j < n; ++j){scanf("%s", word);len = strlen(word);int a = word[0] - 'a';int b = word[len-1] - 'a';degree[a]++;degree[b]--;make_set(a);make_set(b);union_set(a, b);}int ne = 0, ng = 0, nl = 0;for (j = 0; j < ALPHA_NUM; ++j){if (degree[j] == 1){ng++;}else if (degree[j] == -1){nl++;}else if (degree[j] == 0){ne++;}}if (!((ng == 1 && nl == 1 && ne == ALPHA_NUM - 2)  //欧拉通路|| ne == ALPHA_NUM)){  //欧拉回路printf("The door cannot be opened.\n");continue;}for (j = 0; father[j] == -1; ++j);int root = find_set(j);for (j = j+1; j < ALPHA_NUM; ++j){if (father[j] == -1) continue;if (find_set(j) != root){   //所有的节点都有相同的祖先,则图是连通的printf("The door cannot be opened.\n");break;}}if (j == ALPHA_NUM){printf("Ordering is possible.\n");}}}