纯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
");
57 return;
58 }
59 dfs(stx);
60 if(cnt!=m){
61 printf("NO
");
62 return;
63 }
64 printf("YES
");
65 for(int i=cnt-1;i>=0;--i){
66 printf("%d ",ans[i]);
67 }
68 printf("
");
69 }