题目描述
Lambdaland由N个城市组成,任两个城市间都有一条道路相连。
下个月TBL准备参观Lambdaland。他将从城市1开始,以深度优先搜索顺序参观能所有遍历到的城市。 由于TBL是一位十分重要的人物,恐怖分子盯上了他,并在他出发之前炸毁了M条道路。
现在恐怖分子雇佣你写一个程序,求出TBL的参观路线。如果有多解,输出字典序最小的。
20%的分数,N≤1000,M≤50000。
50%的分数,N≤30000,M≤800000。
100%的分数,N≤100000,M≤1000000。
每个城市最多被参观一次,每条道路可被炸毁多次。
思路
暴力dfs,用一个并查集实现把访问过的连续的点缩去,对于一条边$(u,i)$,表示$u,i$直接的道路被炸毁。我们每次访问一个节点$u$时,把出边排序,开一个指针表示下一个跑到哪,用dsu跳到当前字典序最小的,没跑过的点,再用lower_bound判断当前点能不能跑,能跑直接dfs后return
code
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
vector<int>g[N];
int n,m;
int father[N*10];
void init(int x){for(int i=1;i<=x;i++)father[i]=i;}
int find(int x){return x==father[x]?x:father[x]=find(father[x]);}
bool vis[N];
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline void dfs(int u)
{
printf("%d
",u);
vis[u]=1;
father[u]=u+1;
int next=find(1);
sort(g[u].begin(),g[u].end());
while(next<=n)
{
if(!vis[next])
{
int tmp=lower_bound(g[u].begin(),g[u].end(),next)-g[u].begin();
if(tmp>=g[u].size()||next!=g[u][tmp])
{dfs(next);return;}
}next=find(next+1);
}
}
int main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
g[x].push_back(y);
g[y].push_back(x);
}
init(N);
dfs(1);
}