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. Cucumber(1) —— 环境配置

    目录 学习资料 cucumber简介 cucumber环境配置 学习资料 1.cucumber官方学习网站 cucumber简介 1.cucumber是一种支持BBD(behavior-driven ...

  2. 详解 HashMap

    本篇博文的知识点,在我们的日常生活中,应用十分广阔.比如:每个学生,都有自己的对应的学号.每一个公民,都有自己的身份证号- - 相信看到这里,有的同学基本上已经猜到了这个类的主要用途.那么,话不多说, ...

  3. 如何使用Jsoup爬取网页内容

    前言: 这是一篇迟到很久的文章了,人真的是越来越懒,前一阵用jsoup实现了一个功能,个人觉得和selenium的webdriver原理类似,所以今天正好有时间,就又来更新分享了. 实现场景: 爬取博 ...

  4. PHP 语法字符串函数 strcmp、strlen 使用及实现

    说明 这里基于 php7.2.5 进行测试,php7 之后内部结构变化应该不是太大,但与 php5.X 有差别. 函数分类 用户自定义函数 say(); function say() { echo & ...

  5. kubernetes的headless service介绍

    headless service是一个特殊的ClusterIP类service,这种service创建时不指定clusterIP(--cluster-ip=None),因为这点,kube-proxy不 ...

  6. Linux-Discuz安装LAMP

    1.下载,解压Discuz cd /data/discuz wget http://download.comsenz.com/DiscuzX/3.2/Discuz_X3.2_SC_GBK.zip un ...

  7. 文本序列化【通用】word2sequence,文本序列字典保存

    ''' 文本序列化 ''' class WordSequence(): UNK_TAG = "<UNK>" PAD_TAG = "<PAD>&qu ...

  8. vector做形参时的三种传参方式

    vector在做形参的时候传参的方式和普通的变量是一样的,要么传值.要么传引用.要么传指针. 现在分别定义三个以vector为形参的函数: (1) fun1(vector <int> v) ...

  9. css3--:target选择器称为目标选择器

    :target选择器称为目标选择器,用来匹配文档(页面)的url的某个标志符的目标元素.我们先来上个例子,然后再做分析. 示例展示 点击链接显示隐藏的段落. HTML代码: <h2>< ...

  10. auth权限逻辑

    下面本人为大家讲解一下如何实现auth权限, 第一步,新建Auth.php,复制下面的代码,把注释中的表都创建一下.把文件放到extend新建文件夹org放进去即可, <?php // +--- ...