poj 1041 John's trip (Euler Circuit)
输出字典序最小的欧拉回路。之前做过的是要求点的序列最小字典序,今天见到这个经典的欧拉回路是要输出边的编号的最小序。做法跟输出点路径的相似。
View Code
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <set> 5 #include <map> 6 #include <queue> 7 #include <stack> 8 9 using namespace std; 10 11 typedef pair<int, int> PII; 12 typedef multiset<PII> MTPII; 13 #define ITOR iterator 14 #define MPR make_pair 15 #define FI first 16 #define SE second 17 #define REP(i, n) for (int i = 0; i < (n); i++) 18 const int N = 50; 19 MTPII rel[N]; 20 map<int, int> nextVex[N]; 21 int roadCnt; 22 23 int input() { 24 roadCnt = 0; 25 int x, y, z, mk = 0; 26 REP(i, N) rel[i].clear(), nextVex[i].clear();; 27 while (cin >> x >> y && (x || y)) { 28 cin >> z; 29 if (!roadCnt) { 30 mk = min(x, y); 31 } 32 rel[x].insert(MPR(z, y)); 33 nextVex[x][z] = y; 34 rel[y].insert(MPR(z, x)); 35 nextVex[y][z] = x; 36 roadCnt++; 37 } 38 return mk; 39 } 40 41 stack<int> path; 42 43 int check(int mk) { 44 REP(i, N) if (rel[i].size() & 1) return -1; 45 stack<int> tmp = path; 46 int sz = tmp.size(), t; 47 REP(i, sz) { 48 t = tmp.top(); 49 tmp.pop(); 50 if (nextVex[mk].find(t) == nextVex[mk].end()) return -1; 51 mk = nextVex[mk][t]; 52 } 53 return mk; 54 } 55 56 void dfs(int x) { 57 while (!rel[x].empty()) { 58 int edge = (*rel[x].begin()).FI, nx = (*rel[x].begin()).SE; 59 rel[x].erase(rel[x].begin()); 60 rel[nx].erase(MPR(edge, x)); 61 dfs(nx); 62 path.push(edge); 63 } 64 } 65 66 void output() { 67 int sz = path.size(); 68 REP(i, sz) { 69 if (i) putchar(' '); 70 printf("%d", path.top()); 71 path.pop(); 72 } 73 puts(""); 74 } 75 76 int main() { 77 // freopen("in", "r", stdin); 78 int mk; 79 while (mk = input()) { 80 while (!path.empty()) path.pop(); 81 dfs(mk); 82 if ((path.size() == roadCnt) && (check(mk) == mk)) output(); 83 else puts("Round trip does not exist."); 84 } 85 return 0; 86 }
——written by Lyon