欧拉路与欧拉回路
1欧拉回路与欧拉路
1.1定义
- 给定一张无向图,若存在一条从s到t的路径,恰好不重不漏的经过每条边一次,则称改路径为s到t的欧拉路。
- 特别的,若存在一条从s到s的欧拉路,则称该路径为欧拉回路,存在欧拉回路的图被称为欧拉图。
2.1定理
- 欧拉图:一张无向图为欧拉图,当且仅当无向图连通,并且每个点的度数都是偶数。
- 欧拉图=路的存在性判定:一张无向图存在欧拉路,当且仅当无向图联通,并且图中恰好有两个节点的度数为奇数,其他节点的度数都是偶数,这两个度数为奇数的节点就是欧拉路的起点s和t。
2求欧拉回路:
注意:
- 用栈完成拼接
- 用栈模拟递归
- 注意类似于“当前弧优化”
- 输出时倒着输出
- 时间复杂度:\(O(N+M)\)
代码:
inline void ouler(){
stack[++top]=1;
while(top>0){
int x=stack[top],i=head[x];
while(i&&vis[i]) i=next[i];
if(i){
stack[++top]=ver[i];;
vis[i]=vis[i^1]=1;
head[x]=next[i];
}
else{
top--;
ans[++t]=x;
}
}
}
for(int i=t;i>=1;i--) printf("%d",ans[i]);
3例题:
欧拉路的裸题,提醒:用引用来优化map,不用来回调用。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<sstream>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<deque>
#include<cstdlib>
#include<ctime>
#define dd double
#define ld long double
#define ll long long
#define ull unsigned long long
#define N 601000
#define M 601000
using namespace std;
const int INF=0x3f3f3f3f;
inline ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct edge{
int to,next;
inline void intt(int to_,int ne_){
to=to_;next=ne_;
}
};
edge li[M];
int head[N],tail;
inline void add(int from,int to){
li[++tail].intt(to,head[from]);
head[from]=tail;
}
map<string,int> Map;
int tot;
int d[N],sum;
bool vis[N];
inline void dfs(int k){
vis[k]=1;
for(int x=head[k];x;x=li[x].next){
int to=li[x].to;
if(vis[to]) continue;
dfs(to);
}
}
int main(){
while(1){
string s1,s2;
cin>>s1>>s2;
if(s1=="\000") break;
int &from=Map[s1],&to=Map[s2];
if(!from) from=++tot;
if(!to) to=++tot;
add(from,to);add(to,from);
d[from]++;d[to]++;
}
dfs(1);
for(int i=1;i<=tot;i++){
if(!vis[i]){
printf("Impossible\n");
return 0;
}
if(d[i]%2==1) sum++;
}
if(sum!=2&&sum!=0){
printf("Impossible\n");
return 0;
}
printf("Possible\n");
return 0;
}