@description@

给定一张 n 个点 m 条边的无向图,现在想要把这张图定向。

有 p 个限制条件,每个条件形如 \((x_i, y_i)\),表示在新的有向图当中,\(x_i\) 要能够沿着一些边走到 \(y_i\)。

现在请你求出,每条边的方向是否能够唯一确定。同时请给出这些能够唯一确定的边的方向。

输入格式

第一行两个空格隔开的正整数 n, m。

接下来 m 行,每行两个空格隔开的正整数 \(a_i, b_i\),表示 \(a_i, b_i\) 之间有一条边。

接下来一行一个整数 p,表示限制条件的个数。

接下来 p 行,每行两个空格隔开的正整数 \(x_i, y_i\),描述一个 \((x_i, y_i)\) 的限制条件。

输出格式

输出一行一个长度为 m 的字符串,表示每条边的答案:

若第 i 条边必须得要是 \(a_i\) 指向 \(b_i\) 的,那么这个字符串的第 \(i\) 个字符应当为 R;

若第 i 条边必须得要是 \(b_i\) 指向 \(a_i\) 的,那么这个字符串的第 \(i\) 个字符应当为 L;

否则,若第 i 条边的方向无法唯一确定,那么这个字符串的第 \(i\) 个字符应当为 B。

样例输入

5 6

1 2

1 2

4 3

2 3

1 3

5 1

2

4 5

1 3

样例输出

BBRBBL

数据范围与提示

对于 100% 的数据,有 1 <= n, m, p <= 100000。

@solution@

对于无向图转有向图的连通性问题有一个比较常见的结论可以使用:

一个无向图中的边双连通分量可以转成有向图中的强连通分量。

至于为什么,可以结合 tarjan 算法理解:将树边向下连,返祖边向上连,就可以将一个边双连通分量转成强连通分量。

对于一个强连通分量,它内部的点可以互相到达。

同时,将强连通分量内部所有边反转,依然可以互达。这意味着强连通分量内的边总是不可确定方向的。

对应到原图中,原图中边双连通分量内部的边不可以确定方向。

考虑一个限制 (xi, yi),如果同属一个双连通分量则显然可以转成强连通满足限制。

如果不属于同一个双连通分量,因为边双缩点后得到了一棵树,那么 xi -> yi 这条路径上所有缩点后的树边就可以确定方向了。

具体实现,因为总是有解,所以我们可以给每条边设置一个初始为 0 的边权。将 < 0 记为向上,= 0 记为不确定,> 0 记为向下。

然后根据每个限制,对边权加加减减,做一遍树上差分即可。

@accepted code@

#include<cstdio>
#include<algorithm>
using namespace std;
#define rep(G, x) for(graph::edge *p = G.adj[x];p;p = p->nxt)
const int MAXN = 100000;
struct graph{
struct edge{
int to;
edge *nxt, *rev;
}edges[2*MAXN + 5], *adj[MAXN + 5], *ecnt;
graph() {ecnt = edges;}
void addedge(int u, int v) {
edge *p = (++ecnt), *q = (++ecnt);
p->to = v, p->nxt = adj[u], adj[u] = p;
q->to = u, q->nxt = adj[v], adj[v] = q;
p->rev = q, q->rev = p;
}
}G1, G2;
int dfn[MAXN + 5], low[MAXN + 5], dcnt = 0;
int stk[MAXN + 5], id[MAXN + 5], tp = 0, tot = 0;
void dfs1(int x, graph::edge *pre) {
stk[++tp] = x;
dfn[x] = low[x] = (++dcnt);
rep(G1, x) {
if( p->rev == pre ) continue;
if( dfn[p->to] ) low[x] = min(low[x], dfn[p->to]);
else dfs1(p->to, p), low[x] = min(low[x], low[p->to]);
}
if( low[x] >= dfn[x] ) {
tot++;
do{
id[stk[tp]] = tot;
}while( stk[tp--] != x );
}
}
int fa[MAXN + 5];
void dfs2(int x, int f) {
fa[x] = f;
rep(G2, x) {
if( p->to != f )
dfs2(p->to, x);
}
}
bool tag[MAXN + 5]; int d[MAXN + 5];
void dfs3(int x) {
tag[x] = true;
rep(G2, x) {
if( !tag[p->to] )
dfs3(p->to), d[x] += d[p->to];
}
}
int a[MAXN + 5], b[MAXN + 5], n, m, p;
int main() {
scanf("%d%d", &n, &m);
for(int i=1;i<=m;i++) {
scanf("%d%d", &a[i], &b[i]);
G1.addedge(a[i], b[i]);
}
for(int i=1;i<=n;i++)
if( !dfn[i] ) dfs1(i, NULL);
for(int i=1;i<=m;i++)
if( id[a[i]] != id[b[i]] )
G2.addedge(id[a[i]], id[b[i]]);
for(int i=1;i<=tot;i++)
if( !fa[i] ) dfs2(i, 0);
scanf("%d", &p);
for(int i=1;i<=p;i++) {
int x, y; scanf("%d%d", &x, &y);
d[id[x]]--, d[id[y]]++;
}
for(int i=1;i<=tot;i++)
if( !tag[i] ) dfs3(i);
for(int i=1;i<=m;i++)
if( id[a[i]] == id[b[i]] ) putchar('B');
else {
if( fa[id[a[i]]] == id[b[i]] ) {
if( d[id[a[i]]] < 0 ) putchar('R');
else if( d[id[a[i]]] == 0 ) putchar('B');
else putchar('L');
}
else {
if( d[id[b[i]]] > 0 ) putchar('R');
else if( d[id[b[i]]] == 0 ) putchar('B');
else putchar('L');
}
}
puts("");
}

@details@

其实不止树上差分,还有很多方法可以实现最后给边定向,比如并查集。

而且说实话,并查集还要自然一点。

@loj - 2480@ 「CEOI2017」One-Way Streets的更多相关文章

  1. 【刷题】LOJ 2480 「CEOI2017」One-Way Streets

    题目描述 给定一张 \(n\) 个点 \(m\) 条边的无向图,现在想要把这张图定向. 有 \(p\) 个限制条件,每个条件形如 \((xi,yi)\) ,表示在新的有向图当中,\(x_i\) 要能够 ...

  2. loj#2483. 「CEOI2017」Building Bridges 斜率优化 cdq分治

    loj#2483. 「CEOI2017」Building Bridges 链接 https://loj.ac/problem/2483 思路 \[f[i]=f[j]+(h[i]-h[j])^2+(su ...

  3. loj#2483. 「CEOI2017」Building Bridges(dp cdq 凸包)

    题意 题目链接 Sol \[f[i], f[j] + (h[i] - h[j])^2 + (w[i - 1] - w[j]))\] 然后直接套路斜率优化,发现\(k, x\)都不单调 写个cdq就过了 ...

  4. 【动态规划】loj#2485. 「CEOI2017」Chase

    有意思的可做dp题:细节有点多,值得多想想 题目描述 在逃亡者的面前有一个迷宫,这个迷宫由 nnn 个房间和 n−1n-1n−1 条双向走廊构成,每条走廊会链接不同的两个房间,所有的房间都可以通过走廊 ...

  5. @loj - 2483@「CEOI2017」Building Bridges

    目录 @desription@ @solution@ @accepted code@ @details@ @another solution@ @another code@ @desription@ ...

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. TZ_16_Vue_入门案例

    1.新建一个html文件导入vue.js <script src="node_modules/vue/dist/vue.js"></script> 2.创建 ...

  2. 利用webuploader插件上传图片文件,完整前端示例demo,服务端使用SpringMVC接收

    利用WebUploader插件上传图片文件完整前端示例demo,服务端使用SpringMVC接收 Webuploader简介   WebUploader是由Baidu WebFE(FEX)团队开发的一 ...

  3. web前端学习(四)JavaScript学习笔记部分(9)-- JavaScript面向对象详解

    1.认识面向对象 1.1.概念 1.一切事物皆是对象 2.对象具有封装和继承特性 3.信息隐藏(类的信息隐藏,包括属性和方法) <!DOCTYPE html> <html lang= ...

  4. 因子分析spss怎么做 spss因子分析教程及结果解释

    因子分析spss怎么做 spss因子分析教程及结果解释 因子分析spss可以简化数据结构,将具有错综复杂关系的变量综合为数据较少的因子,在信息损失最小的情况下对变量进行分类,不过有些朋友多spss因子 ...

  5. Mybatis+Spring实现Mysql读写分离

    使用spring AbstractRoutingDatasource实现多数据源 public class DynamicDataSource extends AbstractRoutingDataS ...

  6. 【模板】Vector存图 + SPFA

    最近愉快地决定要由边集数组转向Vector存图,顺便开始图论集训 老惯例,以题写模板 P1339 [USACO09OCT]热浪Heat Wave 题目描述 The good folks in Texa ...

  7. 考试总结 模拟27(W)

    心得:太弱了,T1问题:理解错了题,矿石可以放到同一处,,太弱了,小凯的疑惑,没什么印象T2问题:拆式子T3问题:换根dp的思想模拟9T1+T2

  8. Codeforces 455C

    题目链接 C. Civilization time limit per test 1 second memory limit per test 256 megabytes input standard ...

  9. vue2.0 兼容ie9及其以上

    vue官方的意思是vue项目可以在ie8以上的ie版本中运行 但其实使用vue-cli构建的项目也还是不能在ie8[ie9,ie10,ie11]以上的版本中运行 下面就来讲vue如何在ie8以上ie版 ...

  10. 一文读懂JVM

    (一)JVM 基础知识 1)Java 是如何实现跨平台的? 注意:跨平台的是 Java 程序,而不是 JVM.JVM 是用 C/C++ 开发的,是编译后的机器码,不能跨平台,不同平台下需要安装不同版本 ...