[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\n", ans[i]);
        }
    }
    return 0;
}

 

posted @ 2015-08-07 13:33  jklongint  阅读(472)  评论(0编辑  收藏  举报