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. python3+selenium3自动化1——元素定位

    1.selenium的webdriver提供了八种基本的元素定位方法 打开浏览器 driver = webdriver.Chrome() driver.get('https://www.baidu.c ...

  2. Chrome 浏览器安装 ChroPath 插件

    1.下载地址 http://www.cnplugins.com/devtool/chropath/download.html 2.安装方法 a.把下载的文件更改后缀名变为压缩包,然后解压到本地:如下图 ...

  3. Mysql链接查询

    连接查询--交叉连接将两张表的数据与另外一张表彼此交叉原理:1. 从第一张表一次取出每一条记录2. 取出每一条记录之后,与另外一张表的全部记录挨个匹配3. 没有任何匹配条件,所有的结果都会进行保留4. ...

  4. Java 自动拆箱 装箱 包装类的缓存问题--结合源码分析

    都0202 了 java 1.8 已经是主流 自动装箱 .拆箱已经很普遍使用了,那么有时候是不是会遇到坑呢? 我们先来看一段代码: public class TestWraperClass { pub ...

  5. c++使用cin、cout与c中使用scanf、printf进行输入输出的效率问题

    在c++中,我们使用cin和cout进行输入输出会比用scanf和printf更加简洁和方便,但是当程序有大量IO的时候,使用cin和cout进行输入输出会比用scanf和printf更加耗时, 在数 ...

  6. python工业互联网监控项目实战5—Collector到opcua服务

    本小节演示项目是如何从连接器到获取Tank4C9服务上的设备对象的值,并通过Connector服务的url返回给UI端请求的.另外,实际项目中考虑websocket中间可能因为网络通信等原因出现中断情 ...

  7. linux sort 命令实用手册

    Linux 中的sort 命令是一个很实用的工具,用于对文本内容以行为单位进行ASCII 码排序,默认按照升序进行排序(当然也可以按照降序). sort 命令的格式如下: sort `参数` `文件名 ...

  8. jQuery动态时钟

    效果图: 引用的jQuery.js自己百度 代码: <!DOCTYPE html> <html> <head> <meta charset="utf ...

  9. 删除集群mds

    2019独角兽企业重金招聘Python工程师标准>>> 删除cephfs文件系统步骤: 1.停掉服务端mds: #systemctl stop {mds_service} 2.将md ...

  10. Shiro踩坑记(二):使用RequiresXXX的注解后,访问对应请求返回404

    问题描述: 我在项目中的某个Controller上添加了@RequirePermissions注解,希望在执行该请求前,可以先进行权限验证.但是当我请求该Controller时,返回的确是404错误. ...