Hdu 5348 MZL's endless loop (dfs)

题目链接:

  Hdu 5348 MZL's endless loop

题目描述:

  给出一个无向图(有环,有重边),包含n个顶点,m条边,问能否给m条边指定方向,使每个顶点都满足abs(出度-入度)<2。如果能输出任意一种合法方案。

解题思路:

  其实仔细考虑一下,每个无向图都会存在合法方案的。证明:度数和为奇数的点只能为起点或者终点,度数为偶数的只能是环上的起点或者终点或者是中间点。有m条边,一共有2*m个端点。所以呢?当然是度数和为奇数的个肯定是偶数个,任意两个相结合都可以形成一条路。并不会有两条路的起点相同或者终点相同咯。

  由上可知所给的无向图是由若干条路径和若干个环组成的,我们可以对每个点进行dfs,当前遍历的点入度大于出度就正向遍历,否则反向遍历,直到遍历不到边为止。每遍历到一条边就将其删去,遇到环就回溯到环的起点。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #pragma comment (linker, "/STACK:102400000,102400000")
 6 using namespace std;
 7 
 8 const int maxn = 100005;
 9 struct node
10 {
11     int to, next, id;
12 }edge[maxn*6];
13 int head[maxn], du[2][maxn], sum[maxn];
14 int vis[maxn*6], ans[maxn*6], tot;
15 
16 void init ()
17 {
18     tot = 0;
19     memset (head, -1, sizeof(head));
20     memset (du, 0, sizeof(du));
21     //du[0][i]i点的入度,du[1][i]i的出度
22     memset (sum, 0, sizeof(sum));
23     //sum[i]i的度数总和
24     memset (vis, 0, sizeof(vis));
25     //边是否遍历过
26     memset (ans, -1, sizeof(ans));
27 }
28 void Add (int from, int to, int id)
29 {
30     edge[tot].to = to;
31     edge[tot].id = id;
32     edge[tot].next = head[from];
33     head[from] = tot ++;
34 }
35 void dfs (int u, int y)
36 {
37     for (int i=head[u]; i!=-1; i=edge[i].next)
38     {
39         if (vis[i])
40         {//当前边已经被访问过
41             head[u] = edge[i].next;
42             //删边
43             continue;
44         }
45         int v = edge[i].to;
46         if (v!=u && du[y][v]<du[y^1][v])
47             //当前点若和u相连,abs(出度-入度)>1
48             continue;
49         vis[i] = vis[i^1] = 1;
50         if (i % 2)
51             ans[i/2] = y^1;
52         else
53             ans[i/2] = y;
54         du[y][u] ++;
55         du[y^1][v] ++;
56         head[u] = edge[i].next;
57         dfs (v, y);
58         break;
59     }
60 }
61 int main ()
62 {
63     int t, n, m;
64     scanf ("%d", &t);
65     while (t --)
66     {
67         scanf ("%d %d", &n, &m);
68         init ();
69         for (int i=0; i<m; i++)
70         {
71             int u, v;
72             scanf ("%d %d", &u, &v);
73             Add (u, v, i);
74             Add (v, u, i);
75             sum [u] ++;
76             sum [v] ++;
77         }
78         for (int i=1; i<=n; i++)
79         {
80             while (du[0][i] + du[1][i] < sum[i])
81             {
82                 if (du[0][i] <= du[1][i])
83                     dfs (i, 0);
84                 else
85                     dfs (i, 1);
86             }
87         }
88         for (int i=0; i<m; i++)
89             printf ("%d\n", ans[i]);
90     }
91     return 0;
92 }

 

posted @ 2015-08-05 10:44  罗茜  阅读(618)  评论(0编辑  收藏  举报