首页 > 其他分享 >图论----欧拉路径与欧拉回路

图论----欧拉路径与欧拉回路

时间:2022-10-26 21:22:42浏览次数:73  
标签:图论 int pos ---- 回路 include sides 欧拉

好博客:

https://www.acwing.com/solution/content/53434/

https://ycw123.blog.luogu.org/ou-la-hui-lu-yu-ou-la-lu-jing

《介绍与性质》

 

 

 

 

 

 对于无向图来说:

  如果不是欧拉回路:

    起点的度是奇数(度是出度+入度),因为我们从起点出发,如果以后还到达了起点,必然是进入起点,

然后离开起点(因为我这里的前提是:不是欧拉回路,是欧拉路径)。所以度是奇数

    同理,终点的度也是奇数

    其余的中间点度都是偶数

  如果是欧拉回路:

    从起点出发,到起点结束,全部节点的度都是偶数

 

对于有向图来说:

  如果不是欧拉回路:

    起点的出度=起点的入度+1,终点的入度=终点的出度+1

    其余点出度==入度

  如果是欧拉回路:

    全部点:出度==入度

《关于建立图上的注意点》

 在判断是否可以建成欧拉回路或欧拉路径的过程中我们会用上cd[].rd[],表示一个点的出度与入度

在无向图的建立过程中,我一般习惯如下:

 

 这个时候我其实把无向图建立成了上面右边的情况

但是其实当边a->b用过后,b->a边也应该判断为用过

这个时候我判读是否可以有欧拉回路的条件是:

 

 

 像这个图也可以建成欧拉回路,所以不能单独只通过bool vis,这种来判断边是否被看过,特别是在无向图的建边过程中

因为有多个自环与重边在欧拉路径中是被允许的

 《一些问题》

如何记录欧拉路径?

如何在使用vector建边时删去边?

原题:https://www.acwing.com/problem/content/1186/

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <vector>
  5 #include <map>
  6 #include <stack>
  7 using namespace std;
  8 const int N = 1e5 + 5;
  9 int t, n, m, rd[N], cd[N];
 10 struct node
 11 {
 12     int to, w;
 13 };
 14 //在使用结构体map的时候一定要用operator重载一下,否则会报错
 15 struct Node
 16 {
 17     int from, to, w;
 18     bool operator<(const Node &a) const
 19     {
 20         if (a.from == from)
 21         {
 22             if (a.to == to)
 23                 return a.w < w;
 24             else
 25                 return a.to < to;
 26         }
 27         else
 28             return a.from < from;
 29     }
 30 };
 31 stack<int> ans;
 32 vector<node> sides[N];
 33 map<Node, bool> vis;
 34 //用来模拟删除边的数组,pos[i]表示在sides[i]中下次要看的边是
 35 // sides[i][pos[i]],0~pos[i]-1的边都已经看过;
 36 int pos[N];
 37 
 38 void dfs(int x)
 39 {
 40     //这里后面更新是i=max(i+1,pos[x]),而不是i=pos[x]
 41     //是因为可能里面的if语句进不去,防止导致死循环
 42     for (int i = pos[x]; i < sides[x].size(); i = max(i + 1, pos[x]))
 43     {
 44         int to = sides[x][i].to, w = sides[x][i].w;
 45         if (!vis[{x, to, w}])
 46         {
 47             vis[{x, to, w}] = true;
 48             if (t == 1)
 49                 vis[{to, x, -w}] = true;
 50             pos[x] = i + 1;
 51             dfs(sides[x][i].to);
 52             //这是加入边的写法
 53             ans.push(w);
 54         }
 55         //这个加入点的写法
 56         // ans.push(x);
 57     }
 58 }
 59 int main()
 60 {
 61     cin >> t >> n >> m;
 62     for (int i = 1; i <= m; i++)
 63     {
 64         int a, b;
 65         scanf("%d%d", &a, &b);
 66         sides[a].push_back({b, i});
 67         cd[a]++, rd[b]++;
 68 
 69         //表示是无向图时:1
 70         if (t == 1)
 71         {
 72             sides[b].push_back({a, -i});
 73             rd[a]++, cd[b]++;
 74         }
 75     }
 76 
 77     bool flag = true;
 78     for (int i = 1; i <= n; i++)
 79         if ((t == 1 && cd[i] % 2) || (t != 1 && cd[i] != rd[i]))
 80         {
 81             flag = false;
 82             break;
 83         }
 84     if (flag)
 85     {
 86         for (int i = 1; i <= n; i++)
 87             if (sides[i].size() != 0)
 88             {
 89                 dfs(i);
 90                 break;
 91             }
 92 
 93         if (ans.size() != m)
 94             cout << "NO" << endl;
 95         else
 96         {
 97             cout << "YES" << endl;
 98             while (ans.size())
 99             {
100                 cout << ans.top() << " ";
101                 ans.pop();
102             }
103             cout << endl;
104         }
105     }
106     else
107         cout << "NO" << endl;
108     return 0;
109 }

 

无向图模板:

原题链接:https://www.luogu.com.cn/problem/P2731

这里用times[a][b]来记录边a->b的条数,上面不这么用是因为上面的点数太大,开二维会爆,所以以后能开二维就开二维吧,比较容易

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <map>
 5 #include <vector>
 6 #include <stack>
 7 using namespace std;
 8 
 9 typedef pair<int, int> PII;
10 const int N = 510;
11 vector<int> sides[N];
12 int times[N][N];
13 
14 int m, cd[N], rd[N];
15 stack<int> ans;
16 
17 int pos[N];
18 void dfs(int x)
19 {
20     for (int i = pos[x]; i < sides[x].size(); i = max(i + 1, pos[x]))
21     {
22         int to = sides[x][i];
23         if (times[x][to] > 0)
24         {
25             times[x][to]--, times[to][x]--;
26             pos[x] = i + 1;
27             dfs(to);
28         }
29     }
30     ans.push(x);
31 }
32 
33 int main()
34 {
35     cin >> m;
36     int mind = 520, maxd = -520;
37     for (int i = 1; i <= m; i++)
38     {
39         int a, b;
40         scanf("%d%d", &a, &b);
41         mind = min(mind, min(a, b));
42         maxd = max(maxd, max(a, b));
43         sides[a].push_back(b);
44         sides[b].push_back(a);
45         cd[a]++, rd[b]++;
46         cd[b]++, rd[a]++;
47         times[a][b]++, times[b][a]++;
48     }
49     int start = -1;
50     for (int i = mind; i <= maxd; i++)
51     {
52         if (sides[i].size() != 0 && start == -1)
53             start = i;
54         if (sides[i].size() != 0 && cd[i] % 2)
55         {
56             start = i;
57             break;
58         }
59     }
60     for (int i = mind; i <= maxd; i++)
61         sort(sides[i].begin(), sides[i].end());
62 
63     dfs(start);
64 
65     while (ans.size())
66     {
67         cout << ans.top() << endl;
68         ans.pop();
69     }
70 
71     return 0;
72 }

 

标签:图论,int,pos,----,回路,include,sides,欧拉
From: https://www.cnblogs.com/cilinmengye/p/16830040.html

相关文章

  • Python调用matlab函数
    参考文章:安装用于Python的MATLAB引擎API环境:MATLABR2022a、Anaconda、python3.9检验配置检查Python版本是否与Matlab版本相匹配安装API打开matlab在命令行中输入......
  • Winform打包
    1、下载打包工具扩展-->管理扩展-->搜索InstallerProject下载后,要退出vs,会自动安装2、用vs2010打开c#项目,右键点击项目解决方案名称,在弹出的菜单框中选择【添加】→......
  • Java8新特性-Stream
    一、Stream(流)1.1简介1.是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。2.集合讲的是数据,流讲的是计算。3.延迟方法:调用Stream方法之后返回的还是Stream......
  • 做微服务研发工程师的一年来的总结
    前述18年的那个留校夏天,极其偶然接触到了《Docker+Kubernetes》,由纯运维的发展方向转到了云原生运维的发展方向。19年5月以《linuxhelmsmanplatform》获得IT创新大赛二......
  • 事务(Transaction)
    1、什么是事务一个事务是一个完整的业务逻辑单元,不可再分。比如:银行转账,从A账户向B账务转账10000,需要执行两条update语句updatet_actsetbalance=balance-10000w......
  • 存储引擎
    表在数据库中的存储方式。存储引擎只存在mysql中,(Oracle中有对应机制,但是不叫存储引擎)。完整的建表语句:CREATETABLEmytable(idINT(10)PRIMARYKEY,user......
  • 判断是不是闰年
    闰年计算方法:能被400整除。能被4整除,不能被100整除。#include<iostream>usingnamespacestd;classSample{private: intx;public: Sample(){} Sample(int......
  • [AGC040C] Neither AB nor BA
    本题并不难,难点在于一个类似于正难则反的性质。考虑将所有点黑白染色,容易发现,我们删除两个点时不会使其他的点的黑白色发生变化,并且我们删除的每个子串必然跨过黑白两格,......
  • 链表--链表平均分割成几个子链表的方案
    725. SplitLinkedListinPartsMedium36682FavoriteShareGivena(singly)linkedlistwithheadnode ​​root​​​,writeafunctiontosplitthelinkedlisti......
  • 栈的使用以及括号匹配扩展
    678. ValidParenthesisStringMedium68824FavoriteShareGivenastringcontainingonlythreetypesofcharacters:'(',')'and'*',writeafunctiontocheckwhet......