hdu5348 MZL's endless loop(欧拉回路)

本文介绍了一种将无向图转换为有向图的方法,确保每个节点的出入度差不超过1。通过构建欧拉回路并在奇数度节点间补充边来实现。文章还分享了一个ACM竞赛题目的解决方案。

转载请注明出处: http://www.cnblogs.com/fraud/           ——by fraud

 

MZL's endless loop

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 1705    Accepted Submission(s): 369
Special Judge


Problem Description
As we all kown, MZL hates the endless loop deeply, and he commands you to solve this problem to end the loop.
You are given an undirected graph with  n vertexs and m edges. Please direct all the edges so that for every vertex in the graph the inequation |out degree  in degree|1 is satisified.
The graph you are given maybe contains self loops or multiple edges.
 


Input
The first line of the input is a single integer  T, indicating the number of testcases.
For each test case, the first line contains two integers n and m.
And the next m lines, each line contains two integers ui and vi, which describe an edge of the graph.
T1001n1051m3105n2105m7105.
 


Output
For each test case, if there is no solution, print a single line with  1, otherwise output m lines,.
In ith line contains a integer 1 or 01 for direct the ith edge to uivi0 for uivi.
 


Sample Input
2
3 3
1 2
2 3
3 1
7 6
1 2
1 3
1 4
1 5
1 6
1 7
 


Sample Output
1
1
1
0
1
0
1
0
1
 

题意就是给你一张无向图,让你把它变成有向图,使得对于每一个顶点都满足出度与入度的差的绝对值小于等于一

利用欧拉回路,在欧拉图中,每个点的出度都等于入度,那么对于这个图,其实就相当于若干个欧拉图,然后去掉一些边。

然后我们需要做的就是补边。也就是对于每个奇度点,加一条连到其它奇度点的无向边,然后跑欧拉回路,跑的方向就是这条边的方向。

另外注意有多个连通分支。这题比较容易T,虽然我的队友在比赛时瞬间就AC了。。。然而我还是在赛后T了好久,毕竟队友是final选手

  1 /**
  2  * code generated by JHelper
  3  * More info: https://github.com/AlexeyDmitriev/JHelper
  4  * @author xyiyy @https://github.com/xyiyy
  5  */
  6 
  7 #include <iostream>
  8 #include <fstream>
  9 
 10 //#####################
 11 //Author:fraud
 12 //Blog: http://www.cnblogs.com/fraud/
 13 //#####################
 14 #pragma comment(linker, "/STACK:102400000,102400000")
 15 #include <iostream>
 16 #include <sstream>
 17 #include <ios>
 18 #include <iomanip>
 19 #include <functional>
 20 #include <algorithm>
 21 #include <vector>
 22 #include <string>
 23 #include <list>
 24 #include <queue>
 25 #include <deque>
 26 #include <stack>
 27 #include <set>
 28 #include <map>
 29 #include <cstdio>
 30 #include <cstdlib>
 31 #include <cmath>
 32 #include <cstring>
 33 #include <climits>
 34 #include <cctype>
 35 
 36 using namespace std;
 37 #define rep(X, N) for(int X=0;X<N;X++)
 38 
 39 const int MAXN = 800010;
 40 int head[MAXN];
 41 int Next[MAXN], To[MAXN];
 42 int vis[MAXN];
 43 int used[100010];
 44 int deg[100010];
 45 int gao;
 46 int tot;
 47 
 48 void init(int n) {
 49     tot = 0;
 50     rep(i, n)head[i] = -1;
 51 }
 52 
 53 void addedge(int u, int v) {
 54     Next[tot] = head[u];
 55     To[tot] = v;
 56     vis[tot] = 0;
 57     head[u] = tot++;
 58 }
 59 
 60 void eular(int u){
 61     used[u] = 1;
 62     int i;
 63     while(head[u]!=-1){
 64     //for(int &i = head[u];i != -1;i = Next[i]){
 65         i = head[u];
 66         head[u] = Next[head[u]];
 67         if(vis[i])continue;
 68         vis[i^1] = 1;
 69         eular(To[i]);
 70     }
 71 }
 72 int Scan() {
 73     int res=0, ch;
 74     while(ch=getchar(), ch<'0'||ch>'9');
 75     res=ch-'0';
 76     while((ch=getchar())>='0'&&ch<='9')
 77         res=res*10+ch-'0';
 78     return res;
 79 }
 80 void Out(int a) {
 81     if (a > 9)
 82         Out(a / 10);
 83     putchar(a % 10 + '0');
 84 }
 85 
 86 class hdu5348 {
 87 public:
 88     void solve() {
 89         int t;
 90         t =Scan();//in >> t;
 91         while (t--) {
 92             int n, m;
 93             n = Scan();m=Scan();//in >> n >> m;
 94             init(n);
 95             rep(i, n)deg[i] = 0;
 96             int u, v;
 97             rep(i, m) {
 98                 u = Scan();v= Scan();//in >> u >> v;
 99                 u--, v--;
100                 deg[u]++;
101                 deg[v]++;
102                 addedge(u, v);
103                 addedge(v, u);
104             }
105             gao = -1;
106             rep(i, n) {
107                 if (deg[i] & 1) {
108                     if (gao != -1) {
109                         addedge(i, gao);
110                         addedge(gao, i);
111                         gao = -1;
112                     } else gao = i;
113                 }
114             }
115             rep(i, n) used[i] = 0;
116             /*rep(i,n){
117                 if(!used[i]){
118                     dfs(i);
119                     num++;
120                 }
121             }*/
122             gao = -1;
123             rep(i, n) {
124                 if (!used[i]) {
125                     eular(i);
126                 }
127             }
128             m<<=1;
129             for(int i=1;i<m;i+=2){
130                 if (vis[i])putchar('1');
131                 else putchar('0');
132                 putchar('\n');
133             }
134 
135         }
136     }
137 };
138 
139 
140 int main() {
141     //std::ios::sync_with_stdio(false);
142     //std::cin.tie(0);
143     hdu5348 solver;
144     //std::istream &in(std::cin);
145     //std::ostream &out(std::cout);
146     solver.solve();
147     return 0;
148 }

 

转载于:https://www.cnblogs.com/fraud/p/4705833.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值