欧拉图--欧拉通路

离散学过欧拉图的一些知识

今天遇到一个题,挺有趣的。

首先,欧拉图,是指能从任意一点,不重复经过所有边能回到起点的图便是欧拉图。这个路也叫欧拉回路。

次之,欧拉通路,任意一点,不重复经过所有边,不回到起点。这个路叫欧拉通路。

记得书上的分析是从出入度来分析的,

对于无向图,一点的度即是该点连接的边数。

对于有向图,就分为出度和入度。

欧拉回路:

无向图中,所有点都是偶度点,存在欧拉回路。

有向图中,所有点的出度等于入度,存在欧拉回路。

欧拉通路:

无向图中,满足有且仅有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;
}
复制代码

 

posted @   Renhr  阅读(906)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示