[UOJ117] 欧拉回路

描述

有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

一共两个子任务:

  1. 这张图是无向图。(50分)
  2. 这张图是有向图。(50分)

输入格式

第一行一个整数 tt,表示子任务编号。t{1,2}t∈{1,2},如果 t=1t=1 则表示处理无向图的情况,如果 t=2t=2 则表示处理有向图的情况。

第二行两个整数 n,mn,m,表示图的结点数和边数。

接下来 mm 行中,第 ii 行两个整数 vi,uivi,ui,表示第 ii 条边(从 11 开始编号)。保证 1vi,uin1≤vi,ui≤n。

  1. 如果 t=1t=1 则表示 vivi 到 uiui 有一条无向边。
  2. 如果 t=2t=2 则表示 vivi 到 uiui 有一条有向边。

图中可能有重边也可能有自环。

输出格式

如果不可以一笔画,输出一行 “NO”。

否则,输出一行 “YES”,接下来一行输出一组方案。

  1. 如果 t=1t=1,输出 mm 个整数 p1,p2,,pmp1,p2,…,pm。令 e=pie=∣pi∣,那么 ee 表示经过的第 ii 条边的编号。如果 pipi 为正数表示从 veve 走到 ueue,否则表示从 ueue 走到 veve。
  2. 如果 t=2t=2,输出 mm 个整数 p1,p2,,pmp1,p2,…,pm。其中 pipi 表示经过的第 ii 条边的编号。

样例一

input

1
3 3
1 2
2 3
1 3

output

YES
1 2 -3

样例二

input

2
5 6
2 3
2 5
3 4
1 2
4 2
5 1

output

YES
4 1 3 5 2 6

限制与约定 1≤n≤105,0≤m≤2×105

时间限制1s1s

空间限制:256MB

思路

圈套法(弗洛莱算法)

代码实现

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define maxn 100010
 5 #define maxm 400010
 6 struct edge{
 7     int v;
 8     bool ban;
 9     edge *nxt;
10 }ep[maxm];
11 int t,n,m,ecnt,cnt,ind[maxn],outd[maxn],ans[maxm];
12 edge *g[maxn];
13 inline void addedge(int u,int v){
14     edge *p=&ep[ecnt++];
15     p->v=v; p->ban=false; p->nxt=g[u];
16     g[u]=p;
17 }
18 inline edge* rev(edge *j){
19     int i=j-ep;
20     return ep+(i^1);
21 }
22 void dfs_ud(int i){
23     while (g[i])
24         if (!g[i]->ban){
25             edge *j=g[i];
26             j->ban=true;
27             rev(j)->ban=true;
28             dfs_ud(j->v);
29             int tmp=j-ep;
30             if(tmp&1) tmp=-(tmp/2+1);
31             else tmp=tmp/2+1;
32             ans[cnt++]=tmp;
33         }
34         else g[i]=g[i]->nxt;
35 }
36 void dfs_d(int i){
37     while (g[i])
38         if (!g[i]->ban){
39             edge *j=g[i];
40             j->ban=true;
41             dfs_d(j->v);
42             ans[cnt++]=j-ep+1;
43         }
44         else g[i]=g[i]->nxt;
45 }
46 int main(){
47     scanf("%d%d%d",&t,&n,&m);
48     ecnt=0;
49     memset(g,0,sizeof(g));
50     memset(ind,0,sizeof(ind));
51     memset(outd,0,sizeof(outd));
52     for (int i=0;i<m;++i){
53         int u,v;
54         scanf("%d%d",&u,&v);
55         --u,--v;
56         addedge(u,v);
57         ++outd[u];++ind[v];
58         if (t==1) addedge(v,u),++outd[v],++ind[u];
59     }
60     cnt=0;
61     if (t==1){
62         bool flag=true;
63         for (int i=0;i<n;++i)
64             if(ind[i]&1){flag=false;break;}
65         if(!flag) puts("NO");
66         else{
67             for(int i=0;i<n;++i){
68                 dfs_ud(i);
69                 if (cnt) break;
70             }
71             if (cnt==m){
72                 puts("YES");
73                 for (int i=cnt-1; i>=0; --i) printf("%d ",ans[i]);
74                 puts("");
75             }
76             else puts("NO");
77         }
78     }
79     else{
80         edge *p=g[0];
81         while (p) p=p->nxt;
82         bool flag=true;
83         for(int i=0;i<n;++i) if(ind[i]!=outd[i]){flag=false;break;}
84         if (!flag) puts("NO");
85         else{
86             for(int i=0;i<n;++i){
87             dfs_d(i);
88             if(cnt) break;
89             }
90             if(cnt==m){
91                 puts("YES");
92                 for(int i=cnt-1;i>=0;--i) printf("%d ",ans[i]);
93                 puts("");
94             }
95             else puts("NO");
96         }
97     }
98     return 0;
99 }

手动copy的代码,根本看不懂大佬在干嘛呀。

 

56MB

posted @ 2017-06-18 21:40  J_william  阅读(656)  评论(0编辑  收藏  举报