项链,蓝书P309Uva10054(拓扑排序,欧拉回路)

来源:互联网 发布:php 高并发锁机制 编辑:程序博客网 时间:2024/04/28 11:34

本题非常非常有意思,刚开始读完题目以为就是之前做过的有向图求欧拉道路Uva10129单词。但是看完题解之后发现,原来这道题跟“单词”有一个很大的不同点就是,单词不可以翻转,而珠子可以翻转。所以在单词问题中ab,ab并不能连到一起,而本题ab,ab是可以连上的,把珠子ab翻转一下即可。所以单词是一道标准的有向图的题目,但是本题就是一个无向图求欧拉回路的问题。
无论是有向图求欧拉回路还是无向图求欧拉回路,首先判断底图的连通性是最重要的。单纯依靠节点的度数和来判断,无法判断出两个环组成的图的情况(每个节点度数和都为0但是不连通,无欧拉回路)。
但是本题要求就比较简单了,题目并没要求用所有珠子做项链,也没要求判是否能做成项链。只要求判断是否有珠子剩余,这就非常简单了。

// UVa10054 The Necklace// Rujia Liu#include<cstdio>#include<cstring>#include<vector>using namespace std;const int maxcolor = 50;int n, G[maxcolor+1][maxcolor+1], deg[maxcolor+1];struct Edge {  int from, to;  Edge(int from, int to):from(from),to(to) {}};vector<Edge> ans;void euler(int u){  for(int v = 1; v <= maxcolor; v++) if(G[u][v]) {    G[u][v]--; G[v][u]--;    euler(v);    ans.push_back(Edge(u, v));  }}int main() {  int T;  scanf("%d", &T);  for(int kase = 1; kase <= T; kase++) {    scanf("%d", &n);    memset(G, 0, sizeof(G));    memset(deg, 0, sizeof(deg));    int start = -1;    for(int i = 0; i < n; i++) {      int u, v;      scanf("%d%d", &u, &v);      G[u][v]++; G[v][u]++;      deg[u]++; deg[v]++;      start = u;    }    // 无向图的欧拉回路    bool solved = true;    for(int i = 1; i <= maxcolor; i++)      if(deg[i] % 2 == 1) { solved = false; break; } // 检查度数    if(solved) {      ans.clear();      euler(start);      if(ans.size() != n || ans[0].to != ans[ans.size()-1].from) solved = false;    }    printf("Case #%d\n", kase);    if(!solved)      printf("some beads may be lost\n");    else      for(int i = ans.size()-1; i >= 0; i--) printf("%d %d\n", ans[i].from, ans[i].to);    if(kase < T) printf("\n");  }  return 0;}
原创粉丝点击