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

申必的SI120刚好讲到这里,于是回去复习了一下板子。

*知识点部分待补

2.习题

P2731 [USACO3.3] 骑马修栅栏 Riding the Fences

求字典序最小的无向图欧拉路径,图中有孤立点,但保证去掉孤立点的图联通。

const int N=1E3+5;
int n, m;
vector<int> G[N];
int deg[N], mp[N][N], nxt[N];
//nxt下一个遍历到的边
int st[N*8], t;
void dfs_Euler(int x) //Hierholzer 算法
{
for(int i=nxt[x]; i<(int)G[x].size(); i=nxt[x])
{
nxt[x]=i+1;
//边能走则走这条边往下探
if(mp[x][G[x][i]])
{
--mp[x][G[x][i]], --mp[G[x][i]][x];//删边
dfs_Euler(G[x][i]);
}
}
//何时回溯?所有边都走不了了
st[++t]=x;
//回溯的过程就是将回路不断加入路径的过程
}
inline int Solve()
{
#ifdef DEBUG
printf("Debuging...\n");
#endif
n=500, m=read();
for(int i=1; i<=m; i++)
{
int u=read(), v=read();
G[u].push_back(v), ++deg[u];
G[v].push_back(u), ++deg[v];
++mp[u][v], ++mp[v][u];
}
//判定+确定起终点
bool flag=true;
int in=-1, out=-1, min_v=-1;
for(int i=1;flag && i<=n;i++)
{
if(min_v==-1 && deg[i]) min_v=i;
if(deg[i]&1)
{
if(in==-1) in=i;
else if(out==-1) out=i;
else flag=false;
}
}
if(in==-1 && out==-1) in=out=min_v;
if(!flag) return printf("No\n");
//获得字典序最小的路径
for(int i=1; i<=n; i++) sort(G[i].begin(), G[i].end());
dfs_Euler(in);
for(int i=t; i; i--) printf("%d\n", st[i]); putchar('\n');
return 0;
}

P7771 【模板】欧拉路径

求字典序最小的有向图欧拉路径,保证图弱联通。

int n, m;
vector<int> G[N];
int ideg[N], odeg[N], nxt[N]; //mp[N][N]
//nxt下一个遍历到的边
int st[N*8], t;
void dfs_Euler(int x) //Hierholzer 算法
{
for(int i=nxt[x]; i<(int)G[x].size(); i=nxt[x])
{
nxt[x]=i+1;
//边能走则走这条边往下探
//删边: 往后面的边找就是删掉前面的边了
// 有向图也不用根据方向查重
dfs_Euler(G[x][i]);
}
//何时回溯?所有边都走不了了
st[++t]=x;
//回溯的过程就是将回路不断加入路径的过程
}
inline int Solve()
{
#ifdef DEBUG
printf("Debuging...\n");
#endif
n=read(), m=read();
for(int i=1; i<=m; i++)
{
int u=read(), v=read();
G[u].push_back(v);
++ideg[v], ++odeg[u];
}
//判定+确定起终点
bool flag=true;
int in=-1, out=-1, min_v=-1;
for(int i=1;flag && i<=n;i++)
{
if(odeg[i]==ideg[i])
{
if(min_v==-1 && ideg[i]) min_v=i;
}
else if(odeg[i]==ideg[i]+1)
{
if(in==-1) in=i;
else flag=false;
}
else if(odeg[i]+1==ideg[i])
{
if(out==-1) out=i;
else flag=false;
}
else
flag=false;
}
if(in==-1 && out==-1) in=out=min_v;
//else if(in==-1 || out==-1) flag=false;
if(!flag) return printf("No\n");
//获得字典序最小的路径
for(int i=1; i<=n; i++) sort(G[i].begin(), G[i].end());
dfs_Euler(in);
for(int i=t; i; i--) printf("%d ", st[i]); putchar('\n');
return 0;
}
posted @   Coinred  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
点击右上角即可分享
微信分享提示

目录导航