USACO - Riding the Fences (Fleury算法找欧拉路径/欧拉回路模板)

一个blog

题目链接:USACO - Riding the Fences
题意是给定一个图,找到一个描述欧拉路径/欧拉回路的序列,使得序列的字典序最小。

可以用Fleury算法找,实质上是一个dfs。
Fleury算法简单描述就是,每经过一条边,将其删除。当到达一个点时,需要选择一条边进入下一个点,这条边一定不能是割边,否则进去就出不来了,这样就能找到一条欧拉路。
具体用了栈来实现。每经过一个点将其压入栈中,当栈顶无法再访问其他点时,将其放入序列末尾。最后得到的序列就是答案。
我的理解是,当栈顶无法再访问其他点时,说明找到了一条割边连着一条链和一个联通集。既然序列不能是从联通集到链,那么就只能是链到联通集,因此将链放入序列。
如果存在欧拉回路的话,dfs开始的地方就是回路的起点和终点。
如果存在欧拉路径的话,dfs开始的地方是起点。

本题要求字典序最小,因此位于一个点,想进入下一个点时,下一个点必须是最小的那个。
输出的序列是算法实际走的欧拉路的逆序,所以逆序输出就行了。

/*
ID: xdujlx1
PROG: fence
LANG: C++
*/
#include<bits/stdc++.h>
using namespace std;
stack<int> s;
vector<pair<int,int> > adj[507];
bool vis[2500];
int d[507];
int cur[507];
vector<int> ans;
void ioinit()
{
    freopen("fence.in","r",stdin);
    freopen("fence.out","w",stdout);
}
void dfs(int u)
{
    s.push(u);
    for(int& i=cur[u];i<adj[u].size();)
    {
        int now=adj[u][i].first;
        int id=adj[u][i++].second;
        if(vis[id^1]) continue;
        vis[id]=true;
        dfs(now);
    }
    ans.push_back(u);
    s.pop();
}
int main()
{
    ioinit();
    int m,u,v;
    cin>>m;
    int st=507;
    for(int i=0;i<m;i++)
    {
        cin>>u>>v;
        st=min(st,min(u,v));
        ++d[u];++d[v];
        adj[u].push_back(make_pair(v,i<<1));
        adj[v].push_back(make_pair(u,i<<1|1));
    }
    vector<int> t;
    for(int i=1;i<=500;i++)
    {
        if(d[i]&1) t.push_back(i);
    }
    for(int i=1;i<=500;i++)
            sort(adj[i].begin(),adj[i].end());
    if(t.size())
        dfs(min(t[0],t[1]));
    else dfs(st);
    for(int i=ans.size()-1;i>=0;i--)
    {
        printf("%d\n",ans[i]);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值