其他的东西我都跟正解没什么区别,就是关于存储路径的思路。我一开始的思路是:经过某个节点,直接加到答案的序列中,搜了半天,假如发现走不通,那就去掉这个记录。感觉这么办也没问题,可是只有20分。以下是我的代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+2;
const int maxm=2e5+2;
int n,m,s,cnt=-1;
vector<int>edge[maxn];
vector<bool>uss[maxn];
int q[maxm],pre;
int idge[maxn],odge[maxn];
int st[maxn];
void dfs(int x)
{
q[++pre]=x;
cnt++;
if(cnt==m)//访问的边的数量达到m,就输出所有经过的点
{
for(int i=1;i<=pre;i++)
printf("%d ",q[i]);
exit(0);
}
for(int i=st[x];i<edge[x].size();i=max(i+1,st[x]))
if(!uss[x][i])
{
uss[x][i]=1;
st[x]=i+1;
dfs(edge[x][i]);
}
q[pre--]=0;
cnt--;
}
int main()
{
scanf("%d%d",&n,&m);
int a,b;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
odge[a]++;
idge[b]++;
edge[a].push_back(b);
uss[a].push_back(0);
}
for(int i=1;i<=n;i++)
sort(edge[i].begin(),edge[i].end());
a=b=0;
for(int i=1;i<=n;i++)
{
if(abs(idge[i]-odge[i])>1)
{
puts("No");
return 0;
}
if(idge[i]+1==odge[i])
{
a++;
s=i;
if(a>1)
{
puts("No");
return 0;
}
}
if(idge[i]==odge[i]+1)
{
b++;
if(b>1)
{
puts("No");
return 0;
}
}
}
if(s==0)
s=1;
dfs(s);
return 0;
}
我自己调试的时候,发现当出现自环的情况时,会出现一些我自己也难以解释清楚的问题。也许是记录不全。比如,在第一个测试点,有900多条边,我输出了上述代码中变量cnt曾经最大的时候的值,发现只有800多。
后来,我模仿题解里面的思路,先不存,搜完了以后再存,核心的dfs代码如下:
stack<int> ans;
void dfs(int x)
{
for(int i=st[x];i<edge[x].size();i=max(i+1,st[x]))
if(!uss[x][i])
{
uss[x][i]=1;
st[x]=i+1;
dfs(edge[x][i]);
uss[x][i]=0;
}
ans.push(x);
}
然后就AC了。 我不明白,这两种存储的方式的区别究竟在哪里?请大佬指教。