您的位置:首页 > Web前端

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

2017-03-18 12:32 483 查看
一个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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: