题目链接:http://uoj.ac/problem/117
题目大意:
解题思路:先判断度数:
若G为有向图,欧拉回路的点的出度等于入度。
若G为无向图,欧拉回路的点的度数位偶数。
然后判断连通性,并且输出路径需要用套圈法(其实我也不是很懂)。
还学了一些骚操作:
①用链式前向星存图,如果是有向图,那idx隔两个存一条边,如果是无向图则idx隔一个存一条边,且idx从2开始。这样写的作用就是在寻无向图路径时可以良好地标记,比如第一条无向边里idx=2、3分别对应一条正反边,2和3除2都对应1,那么我们只需标记vis[1]就好了,因为欧拉回路只需要用到其中一条边。有向图因为要防止两条当一条用,所以要idx要隔2存一条边。
②在遍历邻接表时j加一个引用,快了超多。
代码:
1 #include<iostream> 2 #include<stack> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=1e5+5; 8 const int M=2e5+5; 9 10 struct node{ 11 int to,next,w; 12 }edge[M*2]; 13 14 int n,m,idx,cnt; 15 int head[N],in_deg[N],out_deg[N],ans[N]; 16 bool vis[M*2]; 17 18 void init(){ 19 idx=2; 20 memset(vis,false,sizeof(vis)); 21 memset(head,0,sizeof(head)); 22 memset(in_deg,0,sizeof(in_deg)); 23 memset(out_deg,0,sizeof(out_deg)); 24 } 25 26 void addedge(int u,int v,int w){ 27 edge[idx].to=v; 28 edge[idx].next=head[u]; 29 edge[idx].w=w; 30 head[u]=idx++; 31 } 32 33 //传说中的套圈法,输出欧拉回路路径 34 void dfs(int u){ 35 //这个引用好神奇啊,速度快了好多,学习了0 0 36 //好像类似于网络流的cur优化(没学过网路流,瞎说的) 37 //然后关于idx的处理也很巧妙 38 for(int &j=head[u];j;j=edge[j].next){ 39 node t=edge[j]; 40 if(!vis[j>>1]){ 41 vis[j>>1]=true; 42 dfs(t.to); 43 ans[++cnt]=t.w; 44 } 45 } 46 } 47 48 int main(){ 49 int t; 50 scanf("%d%d%d",&t,&n,&m); 51 init(); 52 int a,b; 53 for(int i=1;i<=m;i++){ 54 scanf("%d%d",&a,&b); 55 addedge(a,b,i); 56 in_deg[b]++; 57 out_deg[a]++; 58 if(t==1) 59 addedge(b,a,-i); 60 else 61 idx++; 62 } 63 bool flag=true; 64 if(t==1){ 65 for(int i=1;i<=n;i++){ 66 if((in_deg[i]+out_deg[i])%2){ 67 flag=false; 68 break; 69 } 70 } 71 } 72 else{ 73 for(int i=1;i<=n;i++){ 74 if(in_deg[i]!=out_deg[i]){ 75 flag=false; 76 break; 77 } 78 } 79 } 80 if(flag){ 81 dfs(a); 82 if(cnt!=m) 83 puts("NO"); 84 else{ 85 puts("YES"); 86 for(int i=cnt;i>=1;i--){ 87 if(i==1) 88 printf("%d ",ans[i]); 89 else 90 printf("%d ",ans[i]); 91 } 92 } 93 } 94 else 95 puts("NO"); 96 return 0; 97 }