纯dfs,但是由于按大部分板子上dfs,会导致某个点已经dfs过一部分边,但在其他层dfs时又会再次访问这些vis过的边,虽然不进行递归,但是仍然需要for循环过去判断vis,因此极限情况仍然比O(n+m)大很多,亲测cf508D上38组样例卡掉,46ms到2s T掉的差距。不过由于某条边访问过之后一定不会再访问,所以可以直接删去那条边,修改head值就行,这样就能做到O(n+m),额……大概吧

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 using namespace std;
 6 
 7 const int maxn=1005;        //点数
 8 const int maxm=1005*26;        //边数
 9 int head[maxn],size;
10 int point[maxm],nxt[maxm],vis[maxm],ind[maxm];
11 int id[maxn],od[maxn];
12 int cnt;
13 int ans[maxm];
14 void init(){
15     cnt=size=0;
16     memset(head,-1,sizeof(head));
17     memset(vis,0,sizeof(vis));
18     memset(id,0,sizeof(id));
19     memset(od,0,sizeof(od));
20 }
21 void adde(int a,int b,int index){
22     point[size]=b;
23     ind[size]=index;
24     nxt[size]=head[a];
25     head[a]=size++;
26     od[a]++;id[b]++;
27 }
28 void dfs(int s){
29     for(int i=head[s];~i;i=nxt[i]){
30         if(!vis[i]){
31             vis[i]=1;
32             dfs(point[i]);
33             ans[cnt++]=ind[i];
34         }
35     }
36 }
37 //边数较多的图中可能重复遍历已经访问过的边会T,访问一条边直接删一条边可以更加快速
38 /*
39 void dfs(int s){
40     while(~head[s]){
41         int i=head[s];
42         head[s]=nxt[i];
43         dfs(point[i]);
44         ans[cnt++]=ind[i];
45     }
46 }
47 */
48 void solve(int n,int m){        //n点m边
49     int c1=0,c2=0,stx=1;        //stx取标号最小的节点
50     for(int i=1;i<=n;i++){
51         if(od[i]-id[i]==1)c1++,stx=i;
52         else if(od[i]-id[i]==-1)c2++;
53         else if(od[i]-id[i]!=0)c1=3;
54     }
55     if(!((c1==0&&c2==0)||(c1==1&&c2==1))){
56         printf("NO\n");
57         return;
58     }
59     dfs(stx);
60     if(cnt!=m){
61         printf("NO\n");
62         return;
63     }
64     printf("YES\n");
65     for(int i=cnt-1;i>=0;--i){
66         printf("%d ",ans[i]);
67     }
68     printf("\n");
69 }