@sensitive-cs
        
        2019-01-30T07:31:24.000000Z
        字数 1431
        阅读 877
    有一串项链由若干个珠子构成,每两个珠子项链的一端颜色的相同的。
现在给出这些珠子两端的颜色,问用尽所有的珠子能否构成一串项链。
珠子的两端视作点,珠子本身视作边,那么就是从一个点出发遍历完所有的边并且回到起点,因为项链是一个环,所以最后拼接在一起,拼接处的颜色要相同。
那么这就是一个欧拉回路。
需要注意2个地方:
1.判断是否连通,这题的点的序号不一定是连续的;
2.欧拉回路输出路径,需要用到栈来存边,具体见紫书P169。
#include <stdio.h>#include <string.h>#include <algorithm>#include <vector>#include <stack>using namespace std;typedef pair<int,int> pii;stack<pii> s;struct edge{int to;int id;edge(int a,int b){to = a;id = b;}};int dg[55];vector<edge> G[55];bool vis[1005];void dfs(int u){vis[u] = 1;for (auto x : G[u]){if (!vis[x.to]){dfs(x.to);}}}void euler(int u){for (auto x : G[u]){int id = x.id;int to = x.to;if (!vis[id]){vis[id] = 1;euler(to);s.push(pii(u,to));}}}int main(){int T;int cas = 0;scanf("%d",&T);while (T--){memset(dg,0,sizeof(dg));memset(vis,0,sizeof(vis));for (int i = 1;i <= 50;i++) G[i].clear();if (cas) puts("");printf("Case #%d\n",++cas);int n;scanf("%d",&n);int cnt = 0;for (int i = 0;i < n;i++){int x,y;scanf("%d%d",&x,&y);if (!vis[x]){vis[x] = 1;cnt++;}if (!vis[y]){vis[y] = 1;cnt++;}dg[x]++;dg[y]++;G[x].push_back(edge(y,i));G[y].push_back(edge(x,i));}for (int i = 1;i <= 50;i++){if (vis[i]){memset(vis,0,sizeof(vis));dfs(i);break;}}bool f = 0;int num = 0;for (int i = 1;i <= 50;i++){if (vis[i]) num++;}if (num != cnt) f = 1;for (int i = 1;i <= 50;i++){if (dg[i] % 2) f = 1;}if (f){puts("some beads may be lost");continue;}memset(vis,0,sizeof(vis));for (int i = 1;i <= 50;i++){if (dg[i]){euler(i);break;}}while (!s.empty()){auto x = s.top();s.pop();printf("%d %d\n",x.first,x.second);}}return 0;}/*251 22 33 44 55 652 12 23 43 12 4*/