codeforces #288 D(欧拉路)
2015-01-29 10:58:56
思路:和大白书里的例题(uva10054)很像。
以两个字符为一个节点,那么每个字符串(3个字符)就包含了两个节点和一条有向边,比如:abc含义:ab->bc,我们考虑把两个字符看成一个数,由于ASCII码有128位(86年)所以用一个130进制的数来表示两个字符,如:s[0]*130+s[1]。
然后就是求有向图中是否存在一条欧拉路 / 欧拉回路的问题了。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <map> 7 #include <set> 8 #include <stack> 9 #include <queue> 10 #include <string> 11 #include <iostream> 12 #include <algorithm> 13 using namespace std; 14 15 #define MEM(a,b) memset(a,b,sizeof(a)) 16 #define REP(i,n) for(int i=1;i<=(n);++i) 17 #define REV(i,n) for(int i=(n);i>=1;--i) 18 #define FOR(i,a,b) for(int i=(a);i<=(b);++i) 19 #define RFOR(i,a,b) for(int i=(a);i>=(b);--i) 20 #define MP(a,b) make_pair(a,b) 21 22 typedef long long ll; 23 typedef pair<char,char> pii; 24 const int INF = (1 << 30) - 1; 25 const int maxn = 400010; 26 27 int n,anscnt; 28 int deg[maxn],vis[maxn],used[maxn]; 29 char s[maxn][5]; 30 char ans[maxn]; 31 map<int,int> mp; 32 vector<int> ver[maxn]; 33 34 struct edge{ 35 int v,next; 36 }e[maxn]; 37 38 void Euler(int p){ 39 while(!ver[p].empty()){ 40 int v = ver[p].back(); 41 ver[p].pop_back(); 42 Euler(v); 43 ans[++anscnt] = v % 130; 44 } 45 } 46 47 int main(){ 48 int cnt = 0; 49 scanf("%d",&n); 50 REP(i,n){ 51 scanf("%s",s[i]); 52 int a = s[i][0] * 130 + s[i][1]; 53 int b = s[i][1] * 130 + s[i][2]; 54 ver[a].push_back(b); 55 deg[a]++,deg[b]--; 56 } 57 int st = 0,ed = 0,pos = -1; 58 REP(i,20000){ 59 if(deg[i] == 1) st++,pos = i; 60 else if(deg[i] == -1) ed++; 61 else if(deg[i] != 0){ 62 printf("NO\n"); 63 return 0; 64 } 65 } 66 if((st == 1 && ed == 1) || (!st && !ed)){ 67 if(pos == -1) pos = s[1][0] * 130 + s[1][1]; 68 Euler(pos); 69 if(anscnt < n){ 70 printf("NO\n"); 71 return 0; 72 } 73 printf("YES\n"); 74 printf("%c%c",pos / 130,pos % 130); 75 RFOR(i,anscnt,1) printf("%c",ans[i]); 76 puts(""); 77 } 78 else printf("NO\n"); 79 return 0; 80 }