一笔画问题(星存图)
一笔画问题的原理
首先我们要知道怎样可以一笔画
无非就两种情况(图都是连通的)
(P.S.对于一个节点它的度为奇数则称之为奇点)
- 有两个奇点(欧拉路)
- 无奇点(欧拉回路)
我们在处理的时候就要从一个奇点出发,去进行搜索,如果没有奇点那我们就可以任选一个点进行搜索(常常默认为1)
代码实现(可以当作一个模板,对于一些其他题目可以稍作改变然后去交)
#include<bits/stdc++.h>
using namespace std;
int n, tot, m, u, v, minn=0x7f7f7f7f, head[100086], maxx, start, cnt, degree[100086], ans[100086];//head根据点的范围来开
struct edge{
int to, cnt, next;
};
edge e[100086];//edge 根据边的范围来开
void dfs(int temp){
for(int i=head[temp];i;i=e[i].next){
if(e[i].cnt){
e[i].cnt = 0;
if(i&1){
e[i+1].cnt = 0;
}else{
e[i-1].cnt = 0;
}//因为星存图存储无向图是紧挨着的所以可以通过判断当前编号来实现这条路的删除
dfs(e[i].to);
}
}
cnt++;
ans[cnt] = temp;
}
void add(int u, int v){
tot++;
e[tot].next = head[u];
e[tot].to = v;
e[tot].cnt++;
head[u] = tot;
}
int main() {
cin>>n>>m;//n为点,m为边
for(int i=1; i<=m; ++i) {
cin>>u>>v;
add(u, v);
add(v, u);//这两个我在链式前向星存图里面讲述了是对于图的存储
degree[u]++;
degree[v]++;
minn = min(minn, min(u, v));//有的起始点不是1开始的
maxx = max(maxx, max(u, v));//所以要去寻找两个边界点
}
//寻找奇点
start = minn;
for(int i=minn; i<=maxx; ++i) {
if(degree[i]&1){//按位与
start = i;
break;
}
}
dfs(start);
for(int i=1;i<=cnt;++i){
cout<<ans[i]<<" ";
}
return 0;
}