• [hdu5348]图上找环,删环


     http://acm.hdu.edu.cn/showproblem.php?pid=5348

    题意:给一个无向图,现在要将其变成有向图,使得每一个顶点的|出度-入度|<=1

     思路:分为两步,(1)从图上找环,将环上边的方向设为一致,这样直到图中不存在环,最后剩下一个森林(2)对每一棵树的边进行编号,方法是从根节点向下,对每个点,将其与第一个儿子之间的边设置为与父亲之间的边“互补”的方向,而与儿子之间边的方向则交替分配,显然无论儿子多少个,这个点的出度与入度之差不会超过1。这样两步完成后,所有边都有了方向,所以对任意图都是有解的。自环和重边不需要特殊对待。

    无向图上找环: 由于是无向图上任意找环,所以存在这样的性质:如果此时此刻从当前边出发找不到环,那么以后再访问这条边时,也同样找不到环,也就是说如果这条边在某个环上,那么现在就可以找到,所以对同一条边访问一次即可。注意代码里面遍历边时,用一个数组表示这个点边集合的入口,一边遍历一边改变入口,这样下次到这个点时,就跳过了以前访问过的从这个点出发的边。

    至于删环,用数组标记下即可。 

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    #include <map>
    #include <set>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cstdio>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
     
    using namespace std;
     
    #define X                   first
    #define Y                   second
    #define pb                  push_back
    #define mp                  make_pair
    #define all(a)              (a).begin(), (a).end()
    #define fillchar(a, x)      memset(a, x, sizeof(a))
     
    typedef long long ll;
    typedef pair<intint> pii;
    typedef unsigned long long ull;
     
    #ifndef ONLINE_JUDGE
    void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}
    void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>
    void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;
    while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>
    void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
    void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
    void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
    #endif
    template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
    template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
    template<typename T>
    void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}
    template<typename T>
    void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}
     
    const double PI = acos(-1.0);
    const int INF = 1e9 + 7;
     
    /* -------------------------------------------------------------------------------- */
     
    const int maxn = 1e5 + 7;
     
     
    pii E[maxn * 6];
    int SZ;
    int Next[maxn * 6];
    int last[maxn];
     
    int n;
    bool ans[maxn * 6], markE[maxn * 6], dif[maxn], flag[maxn], vis[maxn];
    int mark[maxn];
     
    void add(int u, int v) {
        E[SZ ++] = mp(u, v);
        E[SZ ++] = mp(v, u);
        Next[SZ - 2] = last[u];
        last[u] = SZ - 2;
        Next[SZ - 1] = last[v];
        last[v] = SZ - 1;
    }
    stack<int> S;
    bool now = 0;
    void DeleteRing(int u) {
        if (flag[u]) {
            while (S.top() != u) {
                flag[S.top()] = false;
                S.pop();
            }
            now = true;
            return ;
        }
        S.push(u);
        flag[u] = true;
        for (int &i = mark[u]; ~i; i = Next[i]) {
            int id = i;
            pii &e = E[id];
            if (!vis[e.Y] && !markE[id]) {
                markE[id] = true;
                markE[id ^ 1] = true;
                ans[id] = true;
                DeleteRing(e.Y);
                if (S.top() != u) return ;
                if (now) {
                    now = false;
                    continue;
                }
                markE[id] = false;
                markE[id ^ 1] = false;
                ans[id] = false;
            }
        }
        S.pop();
        flag[u] = false;
        vis[u] = true;
    }
     
    void dfs(int u) {
        vis[u] = true;
        for (int i = last[u]; ~i; i = Next[i]) {
            int id = i;
            pii &e = E[id];
            if (!vis[e.Y] && !markE[id]) {
                markE[id] = true;
                markE[id ^ 1] = true;
                ans[id ^ dif[u]] = true;
                dif[e.Y] = dif[u];
                dif[u] ^= 1;
                dfs(e.Y);
            }
        }
    }
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt""r", stdin);
        //freopen("out.txt", "w", stdout);
    #endif // ONLINE_JUDGE
        int T, u, v, m;
        cin >> T;
        while (T --) {
            cin >> n >> m;
            SZ = 0;
            fillchar(last, -1);
            fillchar(Next, -1);
            fillchar(ans, 0);
            fillchar(vis, 0);
            fillchar(markE, 0);
            for (int i = 0; i < m; i ++) {
                scanf("%d%d", &u, &v);
                add(u, v);
            }
            for (int i = 1; i <= n; i ++) mark[i] = last[i];
            for (int i = 1; i <= n; i ++) {
                if (!vis[i]) DeleteRing(i);
            }
            fillchar(vis, 0);
            fillchar(dif, 0);
     
            for (int i = 1; i <= n; i ++) {
                if (!vis[i]) dfs(i);
            }
            for (int i = 0; i < SZ; i += 2) {
                printf("%d ", ans[i]);
            }
        }
        return 0;
    }
  • 相关阅读:
    马云演讲:给自己一个梦想,给自己一个承诺,给自己一个坚持!
    转:如何成为一个伟大的开发者
    数据挖掘之七种常用的方法
    windows命令行
    100万亿意味着什么?
    ubuntu环境配置
    Ubuntu runlevel修改
    Ubuntu 用户及组管理
    Git学习笔记
    Git详解之三 Git分支
  • 原文地址:https://www.cnblogs.com/jklongint/p/4710534.html
Copyright © 2020-2023  润新知