zoukankan      html  css  js  c++  java
  • 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
    ", ans[i]);
    90     }
    91     return 0;
    92 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    第一次冲刺站立会议03
    第二次冲刺计划会议
    梦断代码阅读笔记02
    学习进度12
    个人项目——找水王
    学习进度11
    梦断代码阅读笔记01
    学习进度10
    学习进度09
    第一次冲刺个人博客10
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4704074.html
Copyright © 2011-2022 走看看