欧拉回路:图G,若存在一条路,从一个节点出发,经过G中每条边有且仅有一次,称这条路为欧拉道路,如果存在一条回路经过G每条边有且仅有一次,
称这条回路为欧拉回路。具有欧拉回路的图成为欧拉图。
判断欧拉道路是否存在的方法
有向图:有一个顶点出度大入度1,有一个顶点入度大出度1,其余都是出度=入度。
无向图:只有两个顶点是奇数度,其余都是偶数度的;或者全为偶数
判断欧拉回路是否存在的方法
有向图:所有的顶点出度=入度。
无向图:所有顶点都是偶数度。
程序实现一般是如下过程:
1.利用并查集判断图是否连通,即判断p[i] < 0的个数,如果大于1,说明不连通,当然用一遍dfs看所有点是否标记也行
2.根据出度入度个数,判断是否满足要求。
3.利用dfs输出路径。
一笔画问题
-
描述
-
zyc从小就比较喜欢玩一些小游戏,其中就包括画一笔画,他想请你帮他写一个程序,判断一个图是否能够用一笔画下来。
规定,所有的边都只能画一次,不能重复画。
(欧拉道路模板)
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 2100
vector <int>mapt[N];
int degree[N];
int single[N];
void dfs(int x);
int main()
{
int T,p,q,a,b,i;
cin>>T;
while(T--){
cin>>p>>q;
memset(degree,0,sizeof(degree));
memset(single,0,sizeof(degree));
for(int i=0;i<q;i++)
{
cin>>a>>b;
mapt[a].push_back(b);
mapt[b].push_back(a);
degree[a]++;
degree[b]++;
}
single[1]=1;
dfs(1);
int flog=1,count=0;
for(i=1;i<=p;i++){
if(!single[i])
{
flog=0;
break;
}
if(degree[i]%2!=0)
count++;
}
if(flog!=0){
if(count==0||count==2)//当奇点为零或二时才存在欧拉道路
printf("Yes\n");
else
printf("No\n");
}
else
printf("No\n");
}
return 0;
}
void dfs(int x)
{
int i;
for(i=0;i<mapt[x].size();i++){
if(single[mapt[x][i]]==0&&mapt[x][i]){
single[mapt[x][i]]=1;
dfs(mapt[x][i]);
}
}
mapt[x].clear();
}
欧拉回路模板题(无向图,有向图)ps混合图哪天碰到在研究研究吧TAT。。。
#117. 欧拉回路
统计有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。
一共两个子任务:
- 这张图是无向图。(50分)
- 这张图是有向图。(50分)
输入格式
第一行一个整数 t ,表示子任务编号。 t∈{1,2} ,如果 t=1 则表示处理无向图的情况,如果 t=2 则表示处理有向图的情况。
第二行两个整数 n,m ,表示图的结点数和边数。
接下来 m 行中,第 i 行两个整数 vi,ui ,表示第 i 条边(从 1 开始编号)。保证 1≤vi,ui≤n 。
- 如果 t=1 则表示 vi 到 ui 有一条无向边。
- 如果 t=2 则表示 vi 到 ui 有一条有向边。
图中可能有重边也可能有自环。
输出格式
如果不可以一笔画,输出一行 “NO”。
否则,输出一行 “YES”,接下来一行输出一组方案。
- 如果 t=1 ,输出 m 个整数 p1,p2,…,pm 。令 e=∣pi∣ ,那么 e 表示经过的第 i 条边的编号。如果 pi 为正数表示从 ve 走到 ue ,否则表示从 ue 走到 ve 。
- 如果 t=2 ,输出 m 个整数 p1,p2,…,pm 。其中 pi 表示经过的第 i 条边的编号。
样例一
input
1 3 3 1 2 2 3 1 3
output
YES 1 2 -3
样例二
input
2 5 6 2 3 2 5 3 4 1 2 4 2 5 1
output
YES 4 1 3 5 2 6
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
using namespace std;
#define N 1000100
#define INF 0x3f3f3f3f
struct edgenode{
int u;
int v;
int next;
}edge[N*4];
int head[N];
int vis[N],pre[N],sum[N];
int n,m,t1;
int cut;
int e1,e2;
int top=0;
inline int read()
{
int x=0;char c=getchar();
while(c<48||c>57)c=getchar();
while(c>47&&c<58)x*=10,x+=c-48,c=getchar();
return x;
}
int eulerdfs1(int now)//无向图
{
for(int i=head[now];~i;i=edge[i].next){
if(vis[i]==0){
vis[i]=1;
if(i & 1){//因为无向图存两条边
vis[i-1]=1;
}
else{
vis[i+1]=1;
}
head[now]=i;//优化,删除了使用的边
eulerdfs1(edge[i].v);
if(i & 1)
pre[top++]=i/2;//数组模仿栈将边存起来
else
pre[top++]=-i/2;
i=head[now];//优化,与上个优化重复可去掉
e1++;
}
}
}
int eulerdfs2(int now)//有向图
{
for(int i=head[now];~i;i=edge[i].next){
if(vis[i]==0){
vis[i]=1;
head[now]=i;
eulerdfs2(edge[i].v);
pre[top++]=i-1;
e2++;
i=head[now];
}
}
}
void add(int u,int v)
{
edge[++cut].u=u;
edge[cut].v=v;
edge[cut].next=head[u];
head[u]=cut;
}
int main()
{
memset(vis,0,sizeof(vis));
//memset(sum,0,sizeof(sum));
memset(head,-1,sizeof(head));
t1=read();
n=read();
m=read();
int a,b;
e1=0;
e2=0;
int flog=0;
cut=1;
if(t1==1){
for(int i=0;i<m;i++){
a=read();
b=read();
add(a,b);
add(b,a);
sum[a]++,sum[b]++;
}
for(int i=1;i<=n;i++)
if(sum[i]&1){
printf("NO\n");
return 0;
}
for(int i=1;i<=n;i++){
if(sum[i]){
eulerdfs1(i);
break;
}
}
if(e1!=m){
printf("NO\n");
return 0;
}
else{
printf("YES\n");
for(int i=0;i<m;i++)
printf("%d ",pre[i]);
//printf("1");
printf("\n");
}
}
else if(t1==2){
for(int i=0;i<m;i++){
a=read();
b=read();
add(a,b);
sum[a]--;
sum[b]++;
}
for(int i=1;i<=n;i++){
if(sum[i]!=0){
printf("NO\n");
return 0;
}
}
for(int i=1;i<=n;i++){
if(~head[i]){//数据的坑。。。有些点没有
eulerdfs2(i);
break;
}
}
// printf("%d %d",e2,cut);
if(e2!=cut-1){
printf("NO\n");
return 0;
}
else{
printf("YES\n");
for(int i=m-1;i>=0;i--)
printf("%d ",pre[i]);
printf("\n");
}
}
return 0;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <vector>
#include <cmath>
#include <set>
using namespace std;
#define N 1000100
#define INF 0x3f3f3f3f
struct edgenode{
int u;
int v;
int next;
}edge[N*4];
int head[N];
int vis[N],pre[N],sum[N];
int n,m,top=0;
int cut;
inline int read()
{
int x=0;char c=getchar();
while(c<48||c>57)c=getchar();
while(c>47&&c<58)x*=10,x+=c-48,c=getchar();
return x;
}
void add(int u,int v)
{
edge[++cut].u=u;
edge[cut].v=v;
edge[cut].next=head[u];
head[u]=cut;
}
void eulrdfs(int now)
{
for(int i=head[now];~i;i=edge[i].next){
if(vis[i]==0){
vis[i]=1;
eulrdfs(edge[i].v);
pre[top++]=edge[i].v;
//printf("%d\n",edge[i].v);
}
}
return ;
}
int main()
{
ios::sync_with_stdio(0);
cin>>n>>m;
int a,b;
cut=0;
top=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
for(int i=1;i<=m;i++){
cin>>a>>b;
add(a,b);
add(b,a);
}
//pre[top++]=1;
eulrdfs(1);
for(int i=0;i<top;i++)
printf("%d\n",pre[i]);
printf("1\n");
}