P6743 [BalticOI 2014 Day2] Senior Postmen 题解

题目描述

P6743 BalticOI 2014 Day2 Senior Postmen

题目解法

看到题目想到直接爆搜。

根据题意,只要找出所有互不相交的简单环即可。题目保证了合法性。

跑 dfs,每次到达一个点 u 就将其放入栈 stk 中。如果栈 stk 中已经有点 u,那么就弹栈。

同时每经过一条边 i,那么就将 visi 设为 1,防止重复计数。

做法和 Tarjan 求联通分量有些相似。

所以:

vector<int> stk;
int ins[maxn], vis[maxn<<1];
void dfs(int u)
{
for(int i=head[u];i;i=nxt[i])
{
if(vis[i]) continue;
vis[i]=vis[i^1]=1;
dfs(to[i]);
}
if(ins[u])
{
while(stk.back()!=u)
{
cout<<stk.back()<<' ';
ins[stk.back()]=0;
stk.pop_back();
}
return cout<<stk.back()<<'\n', void();
}
ins[u]=1;
stk.emplace_back(u);
}

喜提 55ptsTLE on #22 #24


仔细一想,因为每条边只能被使用一次,所以每次可以将 headu 更新为 nxti

修改后:(dfs 函数第三行)

for(int i=head[u];i;i=head[u]=nxt[i])

还是 55pts。只是变成了 TLE on #22


经过一通乱改,最后采取在 dfs 其余节点之前将 headu 更新为 nxti,所以循环处将 i 更新为 headu

修改后:(以及写的极丑的栈)

int stk[maxn], *top=stk;
int ins[maxn], vis[maxn<<1];
void dfs(int u)
{
for(int i=head[u];i;i=head[u])
{
head[u]=nxt[i];
if(vis[i]) continue;
vis[i]=vis[i^1]=1;
dfs(to[i]);
}
if(ins[u])
{
while(*top!=u)
{
cout<<*top<<' ';
ins[*top--]=0;
}
return cout<<*top<<'\n', void();
}
ins[*++top=u]=1;
}

成功 AC

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 500005
int head[maxn], to[maxn<<1], nxt[maxn<<1], tot=1;
void link(int u, int v)
{
to[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int stk[maxn], *top=stk;
int ins[maxn], vis[maxn<<1];
void dfs(int u)
{
for(int i=head[u];i;i=head[u])
{
head[u]=nxt[i];
if(vis[i]) continue;
vis[i]=vis[i^1]=1;
dfs(to[i]);
}
if(ins[u])
{
while(*top!=u)
{
cout<<*top<<' ';
ins[*top--]=0;
}
return cout<<*top<<'\n', void();
}
ins[*++top=u]=1;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1, u, v;i<=m;i++)
{
cin>>u>>v;
link(u, v);
link(v, u);
}
dfs(1);
}

本文作者:redacted-area

本文链接:https://www.cnblogs.com/redacted-area/p/18379529

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Jimmy-LEEE  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起