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;
}

[hdu5348]图上找环,删环的更多相关文章

  1. HDU 2147 kiki's game(博弈图上找规律)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2147 题目大意:给你一个n*m的棋盘,初始位置为(1,m),两人轮流操作,每次只能向下,左,左下这三个 ...

  2. HDU 1253 三维数组的图上找最短路

    题目大意: 从三维空间的(0,0,0)出发到(a-1,b-1,c-1),每移动一个都要时间加一,计算最短时间 根据六个方向,开个bfs,像spfa那样计算最短路径就行了,但是要1200多ms,也不知道 ...

  3. 【学习笔记】有向无环图上的DP

    手动博客搬家: 本文发表于20180716 10:49:04, 原地址https://blog.csdn.net/suncongbo/article/details/81061378 首先,感谢以下几 ...

  4. HDU 3249 Test for job (有向无环图上的最长路,DP)

     解题思路: 求有向无环图上的最长路.简单的动态规划 #include <iostream> #include <cstring> #include <cstdlib ...

  5. qbxt的题:找一个三元环

    有向图中找一个三元环 题意: 考虑 N 个人玩一个游戏, 任意两个人之间进行一场游戏 (共 N*(N-1)/2 场),且每场一定能分出胜负.现在,你需要在其中找到三个人构成的这样的局面:A战胜B,B战 ...

  6. SPFA找最大比例环

    SPFA找最大比例环 ans=Σ点权/Σ边权 所以 可以变式为 Σ边权*ans-Σ点权=0 要找出最大的ans 可以二分 边权值变为 目的地点权-ans*边权 检查是否有负环 有则可以更优 #incl ...

  7. 动态规划 洛谷P4017 最大食物链计数——图上动态规划 拓扑排序

    洛谷P4017 最大食物链计数 这是洛谷一题普及/提高-的题目,也是我第一次做的一题 图上动态规划/拓扑排序 ,我认为这题是很好的学习拓扑排序的题目. 在这题中,我学到了几个名词,入度,出度,及没有环 ...

  8. thinkphp5多图上传 js部分

    在项目中常会用到多图上上传,那就需要多图上传后需要预览,并且能删掉传错(不想传)的图,然而 测试了半天 并不知道jq怎么写,parent()parents()用了半天无果,罢了,还是用原生js来写.这 ...

  9. 2019-ACM-ICPC-南京区网络赛-D. Robots-DAG图上概率动态规划

    2019-ACM-ICPC-南京区网络赛-D. Robots-DAG图上概率动态规划 [Problem Description] ​ 有向无环图中,有个机器人从\(1\)号节点出发,每天等概率的走到下 ...

随机推荐

  1. vue2.x学习笔记(四)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12563162.html. 模板语法 vue使用了基于html的模板语法,允许开发者声明式地将dom绑定到底层vue ...

  2. 小知识点:session的存放位置

    在php.ini里的配置session.save_path是注释掉的,那么Seesion保存的路径在不同类型操作系统保存在什么位置? Linux: /tmp 或 /var/lib/php/sessio ...

  3. Mac下打开 kvm

    mac 下打开 kvm ,需要装这个 https://www.xquartz.org/

  4. Java 多线程 -- 协作模型:生产消费者实现方式二:信号灯法

    使用信号灯法实现生产消费者模式需要借助标志位. 下面以演员表演,观众观看电视为列,写一个demo 同一资源 电视: //同一资源 电视 class Tv { String voice; // 信号灯 ...

  5. 10w+QPS 的 Redis 真的只是因为单线程和内存?360&#176; 深入底层设计为你揭开 Redis 神秘面纱!

    原文链接:10w+QPS 的 Redis 真的只是因为单线程和内存?360° 深入底层设计为你揭开 Redis 神秘面纱! 你以为 Redis 这么快仅仅因为单线程和基于内存? 那么你想得太少了,我个 ...

  6. (第九篇)Iptables详解

    常见的网络攻击形式 1.拒绝服务攻击:DOS 2.分布式拒绝服务攻击 DDOS 3.漏洞入侵 4.口令猜测 以上内容简单了解,具体可自行百度,此处不必知晓. Linux防火墙基础 Linux防火墙体系 ...

  7. Linux操作系统进入单用户模式的方法

    单用户模式的作用 在使用Linux的过程中,维护人员经常会碰到一些问题,就是在拥有root账号权限和密码的用户中,总是会出现忘记root密码的情况. 遇到这种情况,一般情况下,维护人员就会通过最常用的 ...

  8. ansible一键安装mysql8.0

    ansbile安装: # ansible在CentOS7中需要安装epel仓库 yum install -y epel-release yum install -y ansible 安装有好几种方法, ...

  9. QQ网站的源代码

    链接:https://pan.baidu.com/s/1mqetTbauKTI0KJOaU8wW5A 提取码请加QQ:2669803073获取 声明:仅供学习,切勿用于其他用途

  10. 【Linux题目】第六关

    [定时任务规则] 1. 如果在某用户的crontab文件中有以下记录,该行中的命令多久执行一次(RHCE考试题)?( ) 30 4 * * 3 mycmd A. 每小时. B. 每周. C. 每年三月 ...