UOJ 117 欧拉回路(套圈法+欧拉回路路径输出+骚操作)

题目链接: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\n",ans[i]);
89                 else
90                     printf("%d ",ans[i]);
91             }
92         }
93     }
94     else
95         puts("NO");
96     return 0;
97 }

 

posted @ 2017-11-28 22:29  Yeader  阅读(1061)  评论(0编辑  收藏  举报