欧拉图--欧拉通路
离散学过欧拉图的一些知识
今天遇到一个题,挺有趣的。
首先,欧拉图,是指能从任意一点,不重复经过所有边能回到起点的图便是欧拉图。这个路也叫欧拉回路。
次之,欧拉通路,任意一点,不重复经过所有边,不回到起点。这个路叫欧拉通路。
记得书上的分析是从出入度来分析的,
对于无向图,一点的度即是该点连接的边数。
对于有向图,就分为出度和入度。
欧拉回路:
无向图中,所有点都是偶度点,存在欧拉回路。
有向图中,所有点的出度等于入度,存在欧拉回路。
欧拉通路:
无向图中,满足有且仅有0或1对奇度点,即存在欧拉通路(奇度点分别为起点和终点)。
有向图中,满足有且仅有0或1对点的出入度差值为1,即存在欧拉通路(自然,出度多的那个是起点,入度多的那个是终点)。
那么,对代码来说,这也很容易实现,但是但是但是!
对于今日的那个水题:https://www.luogu.com.cn/problem/P1341
我wa了很多次
错误点:
1.大写字母的ascll码比小写字母ascll码大。
2.这题是欧拉通路,没注意奇度点的先后性,也就是,如果有奇度点,得从奇度点开始遍历,而不是直接从小到大找第一个有度的字母,也就是得遍历两次找起点。
3.有重复边的存在,不能简单矩阵存图。
4.这题有重复字母,a->a这种也有,遇到一组数据如下
6
aa
bb
cc
ab
bc
ca
aabbcca
这组数据顺序遍历输出会编程aabbca,少一个c,这是bfs遍历的问题,也即存在最后连不起来的情况。
另外,对于dfs也要注意一个地方,就是需要结束时去存答案,而不是开始遍历前存答案。
原因:https://blog.csdn.net/C20190102/article/details/108141383 这讲的很好了,顺序的时候显然不符合欧拉路径的连通性,跳点了,逆序是符合的。
但是为什么:这样逆序输出 从小到大dfs搜索的 答案 能保证 最后的答案 还是字典序最小的?这个问题还不是很明白,暂留一问吧。
5.连通性问题(虽然这题没出到这种数据,但是也确实是一个wa点)
最后就贴上上述题的代码吧。
#include<iostream> #include<cstring> #include<cstdlib> #include<vector> #include<queue> #include<cmath> #include<map> #include<algorithm> using namespace std; #define N 202 #define mt(x) memset(x,0,sizeof x) typedef long long ll; void cn(ll x){cout<<x<<endl;} void cs(string x){cout<<x<<endl;} vector<int>vc[N]; int n; int vis[N][N],c; char ans[N]; int edge[N]; void add(int x,int y) { vc[x].push_back(y); vc[y].push_back(x); vis[x][y]++; vis[y][x]++; edge[x]++;edge[y]++; } void find(int x) { for(int i='A';i<='z';++i) { if(vis[x][i]) { vis[x][i]--; vis[i][x]--; find(i); } } ans[c++]=x; } bool pd() { int cnt=0,t=0; for(int i='A';i<='z';++i) if(edge[i]%2) { cnt++; if(!t)t=i; } if(!t) { for(int i='A';i<='z';++i) if(edge[i]) { t=i; break; } } if(cnt&&cnt!=2)return false; find(t); return true; } void PR() { while(c)cout<<ans[--c]; cout<<endl; } void solve() { cin>>n; mt(edge); for(int i=0;i<n;++i) { string s; cin>>s; add(s[0],s[1]); } if(!pd()||c!=n+1)cs("No Solution"); else PR(); } int main() { ios::sync_with_stdio(false); cin.tie(0); solve(); return 0; }

浙公网安备 33010602011771号