poj 2337 Catenyms(欧拉路+字典序+打印路径)
2014-04-18 20:11
387 查看
http://poj.org/problem?id=2337
题目大意:给出一组单词,如果两个单词,一个单词的头和另一个单词的尾相同,则可以相连,例如abce, efdg,可以相连,问这组单词能否排成一排,如果可以,求出字典序最小的那个。
思路:重点在建图。将单词的两个端点为顶点建有向边,用邻接表存储,用头插法建邻接表时,首先应对输入的字符串从大到小排序,这样才能保证按字典序输出。
首先判断图的连通性,然后判断是否欧拉路或欧拉通路。若是欧拉路,以出度大入度为1的点为起点,若是欧拉回路则以字典序最小的点为起点进行dfs。
题目大意:给出一组单词,如果两个单词,一个单词的头和另一个单词的尾相同,则可以相连,例如abce, efdg,可以相连,问这组单词能否排成一排,如果可以,求出字典序最小的那个。
思路:重点在建图。将单词的两个端点为顶点建有向边,用邻接表存储,用头插法建邻接表时,首先应对输入的字符串从大到小排序,这样才能保证按字典序输出。
首先判断图的连通性,然后判断是否欧拉路或欧拉通路。若是欧拉路,以出度大入度为1的点为起点,若是欧拉回路则以字典序最小的点为起点进行dfs。
#include <stdio.h> #include <string.h> #include <algorithm> #include <stack> #include <vector> #define LL long long #define _LL __int64 using namespace std; struct node { int u,v; int next; char str[22]; int vis; bool operator < (const struct node &tmp)const { if(strcmp(str,tmp.str) > 0) return true; return false; } }s[1010]; int in[1010],out[1010]; //保存每个点的出入度 int cnt;//顶点个数 int ok[26];//ok[i] = 1 : i+'a'是顶点 int set[26]; int start,end;//记录欧拉路的起点与终点 int head[26]; char ans[1010][22];//保存输出结果 int c; void init() { memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(ok,0,sizeof(ok)); cnt = 0; for(int i = 0; i < 26; i++) set[i] = i; memset(head,-1,sizeof(head)); c = 0; } int find(int x) { if(set[x] != x) set[x] = find(set[x]); return set[x]; } //并查集判断是否图是否连通 bool check() { int flag = 1; for(int i = 0; i < 26; i++) { if(!ok[i]) continue; for(int j = i+1; j < 26; j++) { if(!ok[j]) continue; if(find(i) != find(j)) { flag = 0; break; } } if(!flag) break; } if(flag) return true; return false; } //判断是欧拉路还是欧拉回路 int judge() { int c1 = 0,c2 = 0,c3 = 0; for(int i = 0; i < 26; i++) { if(ok[i]) { if(in[i] == out[i]) c3++; else if(in[i]-out[i] == 1) { end = i; c1++; } else if(out[i]-in[i] == 1) { start = i; c2++; } } } if(c3 == cnt) return 2; //欧拉回路 else if(c1 == 1 && c2 == 1 && c3 == cnt-2) //欧拉路 return 1; else return 0; } //dfs寻找欧拉路或欧拉回路,注意输出是逆序输出 void dfs(int u) { for(int i = head[u]; i != -1; i = s[i].next) { if(!s[i].vis) { s[i].vis = 1; dfs(s[i].v); strcpy(ans[c++],s[i].str); } } } int main() { int test,n,u,v; scanf("%d",&test); while(test--) { init(); scanf("%d",&n); for(int i = 0; i < n; i++) { scanf("%s",s[i].str); s[i].vis = 0; } sort(s,s+n); //对边从大到小排序 for(int i = 0; i < n; i++) { int len = strlen(s[i].str); u = s[i].str[0]-'a'; v = s[i].str[len-1]-'a'; if(!ok[u]) { ok[u] = 1; cnt++; } if(!ok[v]) { ok[v] = 1; cnt++; } //头插法建边 s[i].u = u; s[i].v = v; s[i].next = head[u]; head[u] = i; out[u]++; in[v]++; int uu = find(u); int vv = find(v); if(uu != vv) set[uu] = vv; } if(!check()) { printf("***\n"); continue; } int res = judge(); if(!res) { printf("***\n"); continue; } else if(res == 1) //欧拉路 { dfs(start); } else //欧拉回路 { for(int i = 0; i < 26; i++) { if(ok[i]) { start = i; break; } } dfs(start); } printf("%s",ans[c-1]); for(int i = c-2; i >= 0; i--) printf(".%s",ans[i]); printf("\n"); } return 0; }
相关文章推荐
- POJ 2337 && ZOJ 1919--Catenyms 【有向图 && 欧拉路判断 && 欧拉路径】
- poj 2337 Catenyms(欧拉路径的最小字典序)
- POJ 2337 Catenyms(有向图欧拉路径判定&&打印)
- POJ ~ 2337 ~ Catenyms (欧拉路 + 路径输出)
- POJ 2337 - Catenyms 按所需的字典序输出欧拉路径..
- poj 2337 Catenyms (边最小字典序欧拉路径 Fleury)
- POJ 2337 Catenyms(欧拉路径)
- POJ - 2337 Catenyms(欧拉回路+dfs输出路径)
- POJ 2337 Catenyms (有向图欧拉路径,求字典序最小的解)
- poj 2337 Catenyms(欧拉路径)
- poj 2337 Catenyms 有向图欧拉路径
- poj 2337 Catenyms 判断并输出欧拉路 判断N个字符串是否能够首尾相连全部输出(欧拉路)
- POJ 2337 Catenyms(有向欧拉图:输出欧拉路径)
- poj 2337 Catenyms 欧拉路
- zoj 1919 poj 2337 Catenyms(欧拉路径求解)
- POJ-2337-Catenyms(欧拉路)
- poj 2337 Catenyms(欧拉路径+并查集)
- poj 2337 Catenyms 欧拉路的输出
- poj 2337 Catenyms 【欧拉路径】
- poj 2337 Catenyms 【欧拉路径】