欧拉回路&欧拉路径学习笔记

基础性质(用来判定):
1.无向图欧拉回路没有奇数点 (有向图所有点入度等于出度)
2.无向图欧拉路径只有两个奇数点 (有向图有一个顶点入度比出度大1,有一个顶点出度比入度大1,其他的全相等)
3.图连通
找欧拉回路(找不到时找到欧拉路径)算法\(Hierholzer\)
STEP0:判连通性(并查集||dfs||tarjan)
STEP1: 判断奇数点个数(即是否本图有欧拉回路),并寻找起点,如果有奇数点那么他们一定其中一个是起点,如果,没有奇数点则可以随意指定起点
STEP2:从起点开始dfs,对于从u到v点一条边,删除e(u,v)这条边,如果v没有出边,将v入栈,递归到v
STEP3:倒序出输序列
注释:因为欧拉回路在一张图中有很多个,题目常常会要求字典序,所以我会用multiset存图
例题:
1.lougu1341
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<set>
using namespace std;
const int MAXX=10000;
multiset<int>to[MAXX];
int f[MAXX],deg[MAXX],q[MAXX];
int n,tot,ans,cnt,s=-1;
bool vis[MAXX],num[MAXX],flag;
inline int find(int x){
    if(f[x]==x)return x;
    else return f[x]=find(f[x]);
}
inline void dfs(int x){
    for(set<int>:: iterator it=to[x].begin();it!=to[x].end();it=to[x].begin()){
        int y=*it;
        to[x].erase(it);
        to[y].erase(to[y].find(x));
        dfs(y);
    }
    q[++tot]=x;
}
int main(){
   cin>>n;
   for(int i=0;i<=99;++i)f[i]=i;
   for(int i=1;i<=n;++i){
    char a,b;
    int x,y;
    cin>>a>>b;
    x=a-'A';y=b-'A';
    int u=find(x);
    int v=find(y);
    f[u]=v;
    vis[x]=1;vis[y]=1;
    deg[x]++;deg[y]++;
    to[x].insert(y);
    to[y].insert(x);
   }
   for(int i=0;i<=99;++i){
      if(!vis[i])continue;
      num[find(i)]=1;
   }
   for(int i=0;i<=99;++i){
    if(!vis[i])continue;
    ans+=num[i];
    if(s==-1)s=i;
    if(deg[i]&1){
        cnt++;
        if(flag)continue;
        s=i;
        flag=1;
    }
   }
   if((cnt!=0&&cnt!=2)||ans>1){
    cout<<"No Solution"<<endl;
    return 0;
   }
   dfs(s);
   for(int i=tot;i>=1;--i){
    char ss='A'+q[i];
    cout<<ss;
   }
   return 0;
}

转载于:https://www.cnblogs.com/ARTlover/p/9546644.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值