SGU---101 无向图的欧拉回路
题目链接:
https://cn.vjudge.net/problem/SGU-101
题目大意:
给定你n张骨牌,每张牌左右两端有一个数字,每张牌的左右两端数字可以颠倒,找出一种摆放骨牌的顺序,使得相邻骨牌的两端数字相同(最左边骨牌的最左端和最右边骨牌的最右端可以不管)。
解题思路:
直接求解无向图的欧拉回路即可。 欧拉回路相关定理
此处建模把每张牌看做一条边,牌左右两端的数字为起点和终点。存边的时候存两条,一条正向边,一条反向边
首先判断度数关系,存在欧拉道路回路的条件是连通图不存在或者仅存在两个奇度顶点。
注意DFS找欧拉路径后存入ans栈中,需要判断ans内存入的边的数量是否为n,不为n则图不连通。
简单题,但是一个小细节出错,就是下述代码中找起点s的那里写错了。Wa了好几次
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef pair<int, int> Pair;//first存终点,second存编号,正向边存正编号,反向边存负编号 4 vector<Pair>G[10];//邻接表存图 5 int num[7];//度数 6 bool vis[105];//某条边是否已经遍历 7 stack<int>ans;//欧拉道路 8 void euler(int u) 9 { 10 for(int i = 0; i < G[u].size(); i++) 11 { 12 int v = G[u][i].first; 13 int id = G[u][i].second; 14 if(!vis[abs(id)]) 15 { 16 vis[abs(id)] = 1; 17 euler(v); 18 ans.push(id); 19 } 20 } 21 } 22 int main() 23 { 24 int n, u, v; 25 scanf("%d", &n); 26 for(int i = 1; i <= n; i++) 27 { 28 scanf("%d%d", &u, &v); 29 num[u]++, num[v]++; 30 G[u].push_back(Pair(v, i)); 31 G[v].push_back(Pair(u, -i)); 32 } 33 int tot = 0; 34 for(int i = 0; i <= 6; i++)//注意选择起点 35 if(num[i] & 1)tot++; 36 if(tot == 0 || tot == 2) 37 { 38 int s;//选择起点时要分类讨论 不然选到的点可能不是奇度顶点或者是度数为0的点 39 if(tot) 40 { 41 for(int i = 0; i <= 6; i++) 42 if(num[i] & 1)s = i; 43 }//此处没有花括号的话,else和循环内的if配对,之前没写这个一直WA 44 else 45 for(int i = 0; i <= 6; i++)if(num[i])s = i; 46 euler(s); 47 if(ans.size() != n)//图不连通 48 { 49 printf("No solution\n"); 50 return 0; 51 } 52 while(!ans.empty()) 53 { 54 if(ans.top() > 0) 55 printf("%d +\n", ans.top()); 56 else printf("%d -\n", -ans.top()); 57 ans.pop(); 58 } 59 } 60 else printf("No solution\n"); 61 return 0; 62 }
越努力,越幸运