相信很多同学都卡在超时
其他原理我就不阐述了
就讲讲我是怎么克服超时的
为什么会超时
算法本身是线性的
但在删边时由于我们只是标记一下
就要重复遍历一个边好多遍
怎么克服这个呢?
就要在删边上做优化
我用的是前向星存图
类比链表的删点的方法
直接把这个边从链上拆下来
下次再遍历这个点的边时,这个边就不会被遍历
程序如下:
#include<bits/stdc++.h>
using namespace std;
int t,n,m,a,b;
struct oppo{
int to,next;
}rood[500005];
int head[100005],tot=1;
void add(int from,int to)
{
rood[++tot].to=to;
rood[tot].next=head[from];
head[from]=tot;
}
stack< int > ans;
bool flag[400005];
int all;
void dfs(int x)
{
int tot=0;
for(int i=head[x];i;i=head[x]){
head[x]=rood[i].next;
if(flag[i/t-t%2])
continue;
flag[i/t-t%2]=1;
dfs(rood[i].to);
all++;
if(t==1)
ans.push(i/t-t%2);
else
ans.push((i/t-t%2)*pow(-1,i%2));
}
}
int pd[100005];
int dp[100005];
int main()
{
cin>>t;
if(t==1)//我为什么要交换呢???
t=2;//因为代码打完了才发现 t的1,2 读题是理解反了
else
t=1;
cin>>n>>m;
if(t==1){
for(int i=1;i<=m;i++){
scanf("%d %d",&a,&b);
add(a,b);
pd[a]++;
dp[b]++;
}
for(int i=1;i<=n;i++)
if(pd[i]!=dp[i]){
puts("NO");
return 0;
}
}
else if(t==2){
for(int i=1;i<=m;i++){
scanf("%d %d",&a,&b);
add(a,b);add(b,a);
pd[a]++;
pd[b]++;
}
for(int i=1;i<=n;i++)
if(pd[i]%2){
puts("NO");
return 0;
}
}
for(int i=1;i<=n;i++)
if(head[i]){
dfs(i);
break;
}
if(all!=m){
puts("NO");
return 0;
}
puts("YES");
while(ans.size()){
printf("%d ",ans.top());
ans.pop();
}
return 0;
}