[CEOI2017]One-Way Streets
题目大意:
给你一个无向图,现在告诉你一些点对(u,v),
要你在保证从u到v的所有路径都不变的情况下,尽可能把所有的边变成单向边,
问你可以唯一确定哪些边的方向,以及方向是从u到v还是从v到u。
思路:
首先不难发现环上的边都不能确定方向,所以我们可以先缩环。
缩环以后剩下的图就变成了一棵树,考虑对树进行一些操作来确定边的方向。
我们可以树链剖分,用线段树维护边的方向,
但是树上边的方向不一定都是同一种,因此我们可以先不考虑从u到v还是从v到u。
我们只需要先维护从上到下还是从下到上。
如果维护时发现当前维护的边的区间已经是有向的,而且和当前方向相反,那么就是双向边。
最后统计答案时,只需要判一下u在上还是v在上即可。
小优化:当维护区间已经是双向时,不管怎样它永远都是双向了,我们可以直接在线段树上剪枝。
#include<stack>
#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=,M=;
struct Edge2 {
int u,v;
};
Edge2 edge[M];
struct Edge {
int to,id;
};
std::vector<Edge> e[N];
inline void add_edge(const int &u,const int &v,const int &id) {
e[u].push_back((Edge){v,id});
e[v].push_back((Edge){u,id});
}
char type[M];
std::stack<int> s;
bool mark[M],ins[N];
int dfn[N],low[N],bcc[N];
void tarjan(const int &x) {
s.push(x);
ins[x]=true;
dfn[x]=low[x]=++dfn[];
for(unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i].to,&id=e[x][i].id;
if(mark[id]) continue;
mark[id]=true;
if(!dfn[y]) {
tarjan(y);
low[x]=std::min(low[x],low[y]);
} else if(ins[y]) {
low[x]=std::min(low[x],dfn[y]);
}
}
if(dfn[x]==low[x]) {
bcc[]++;
int y=;
while(y!=x) {
y=s.top();
s.pop();
ins[y]=false;
bcc[y]=bcc[];
}
}
}
int par[N],size[N],dep[N],son[N],top[N],id[N],ori[N];
void dfs1(const int &x,const int &par) {
size[x]=;
::par[x]=par;
dep[x]=dep[par]+;
for(unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i].to;
if(y==par) continue;
dfs1(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
void dfs2(const int &x) {
if(x==son[par[x]]) {
top[x]=top[par[x]];
} else {
top[x]=x;
}
if(son[x]) {
id[son[x]]=++id[];
dfs2(son[x]);
}
for(unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i].to;
if(y!=par[x]&&y!=son[x]) {
id[y]=++id[];
dfs2(y);
}
ori[id[y]]=e[x][i].id;
}
}
class SegmentTree {
#define _left <<1
#define _right <<1|1
private:
char val[N<<];
void push_down(const int &p) {
if(!val[p]) return;
if(val[p _left]) {
if(val[p _left]!=val[p]) val[p]='B';
} else {
val[p _left]=val[p];
}
if(val[p _right]) {
if(val[p _right]!=val[p]) val[p]='B';
} else {
val[p _right]=val[p];
}
}
public:
void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const char &c) {
if(val[p]=='B') return;
if(b==l&&e==r) {
if(val[p]) {
if(val[p]!=c) val[p]='B';
} else {
val[p]=c;
}
return;
}
push_down(p);
const int mid=(b+e)>>;
if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),c);
if(r>mid) modify(p _right,mid+,e,std::max(mid+,l),r,c);
}
void stat(const int &p,const int &b,const int &e) {
if(val[p]=='B') return;
if(b==e) {
if(val[p]) {
type[ori[b]]=val[p];
} else {
type[ori[b]]='B';
}
return;
}
push_down(p);
const int mid=(b+e)>>;
stat(p _left,b,mid);
stat(p _right,mid+,e);
}
#undef _left
#undef _right
};
SegmentTree t;
void modify(int x,int y) {
char c='R',c0='L';
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) {
std::swap(x,y);
std::swap(c,c0);
}
t.modify(,,bcc[],id[top[x]],id[x],c);
x=par[top[x]];
}
if(x==y) return;
if(dep[x]<dep[y]) {
std::swap(x,y);
std::swap(c,c0);
}
t.modify(,,bcc[],id[son[y]],id[x],c);
}
int main() {
const int n=getint(),m=getint();
for(register int i=;i<=m;i++) {
edge[i]=(Edge2){getint(),getint()};
add_edge(edge[i].u,edge[i].v,i);
}
for(register int i=;i<=n;i++) {
if(!dfn[i]) tarjan(i);
e[i].clear();
}
for(register int i=;i<=m;i++) {
const int &u=edge[i].u,&v=edge[i].v;
if(bcc[u]==bcc[v]) {
type[i]='B';
continue;
}
add_edge(bcc[u],bcc[v],i);
}
for(register int i=;i<=bcc[];i++) {
if(!size[i]) {
dfs1(i,);
id[i]=++id[];
dfs2(i);
}
}
for(register int q=getint();q;q--) {
const int x=bcc[getint()],y=bcc[getint()];
modify(x,y);
}
t.stat(,,bcc[]);
for(register int i=;i<=m;i++) {
const int &u=bcc[edge[i].u],&v=bcc[edge[i].v];
if(type[i]!='B'&&dep[u]<dep[v]) {
if(type[i]=='L') {
type[i]='R';
} else {
type[i]='L';
}
}
}
puts(&type[]);
return ;
}
[CEOI2017]One-Way Streets的更多相关文章
- 【刷题】LOJ 2480 「CEOI2017」One-Way Streets
题目描述 给定一张 \(n\) 个点 \(m\) 条边的无向图,现在想要把这张图定向. 有 \(p\) 个限制条件,每个条件形如 \((xi,yi)\) ,表示在新的有向图当中,\(x_i\) 要能够 ...
- @loj - 2480@ 「CEOI2017」One-Way Streets
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一张 n 个点 m 条边的无向图,现在想要把这张图定向. 有 ...
- Luogu4652 CEOI2017 One-Way Streets 树上差分
传送门 题意:给出$N$个点.$M$条无向边的图,现在你需要给它定向,并满足$Q$个条件:每个条件形如$(x_i,y_i)$,表示定向之后需要存在路径从$x_i$走向$y_i$.问每条边是否都有唯一定 ...
- loj2480 [CEOI2017]One-Way Streets 边双+树上差分
边双无法确定 缩完边双就是一棵树 树上差分随意弄一下吧... #include <vector> #include <cstdio> #include <cstring& ...
- One-Way Streets (oneway)
One-Way Streets (oneway) 题目描述 Once upon a time there was a country with nn cities and mm bidirection ...
- Luogu4655 [CEOI2017]Building Bridges
Luogu4655 [CEOI2017]Building Bridges 有 \(n\) 根柱子依次排列,每根柱子都有一个高度.第 \(i\) 根柱子的高度为 \(h_i\) . 现在想要建造若干座桥 ...
- Codeforces 1070J Streets and Avenues in Berhattan dp
Streets and Avenues in Berhattan 我们首先能发现在最优情况下最多只有一种颜色会分别在行和列, 因为你把式子写出来是个二次函数, 在两端取极值. 然后我们就枚举哪个颜色会 ...
- 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 ...
- [CEOI2017]Palindromic Partitions
[CEOI2017]Palindromic Partitions 题目大意: 给出一个长度为\(n(n\le10^6)\)的只包含小写字母字符串,要求你将它划分成尽可能多的小块,使得这些小块构成回文串 ...
随机推荐
- Codeforces Round #478 C. Valhalla Siege
C. Valhalla Siege time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- Spring学习--依赖注入的方式
Spring 依赖注入: 属性注入(最常使用) 构造函数注入 工厂方法注入(很少使用,不推荐) 属性注入:通过 setter 方法注入 Bean 的属性值或依赖的对象 , 使用<property ...
- 调用webservice接口
这里是cxf服务器,采用myeclipse6.5,把wsdl放到本地的方式. 新建一个包, 把解析到的类放在这个包下面. 生成的代码结构: 调用: public static String callI ...
- 关于CRC循环冗余校验的总结(C#)
1. 实验要求 (1)通过CRC(循环冗余校对)序列的计算,掌握C#语言中类的静态方法与动态方法的区别. (2)Shell与Windows Form 的通信作为扩展提高内容. 2. 实验内容 主要工 ...
- LOJ tangjz的背包
题目大意 有 \(n\) 个物品, 第 \(i\) 个物品的体积为 \(i\) 令 \(f(x)\) 为 选择 \(m\) 个物品, 体积和为 \(x\) 的方案数 令 \(V = \sum_{i=1 ...
- Spring MVC框架下 从后台读取数据库并显示在前台页面【笔记自用 不推荐作为参考】
1.书写jsp页面 people.jsp 1.设计显示格式以及内容显示 2.设计显示内容的范围 2.书写entity实体类 PeopleFormMap.java 书写传入的参数主要包括 要引用的数据 ...
- request.getParameterValues与request.getParameter的区别
一. 简单的对比 request.getParameter用的比较多,相对熟悉 request.getParameterValues(String name)是获得如checkbox类(名字相同, ...
- 【hdu4436/LA6387-str2int】sam处理不同子串
题意:给出n个数字,数字很长,用字符串读入,长度总和为10^5.求这n个字符串的所有子串(不重复)的和取模2012 . 例如字符串101,和就是1+10+101=112. 题解: 就是求不同的子串连成 ...
- 【洛谷 P2515】 [HAOI2010]软件安装 (缩点+树形背包)
题目链接 看到代价和价值这两个关键词,肯定是首先要想到背包的. 但是图中并没有说这是棵树,所以先要\(Tarjan\)缩点,然后就是选课了,跑一遍树形背包就好了. 注意:缩点后应该是一个森林,应该用一 ...
- [bzoj4034][HAOI2015]树上操作——树状数组+dfs序
Brief Description 您需要设计一种数据结构支持以下操作: 把某个节点 x 的点权增加 a . 把某个节点 x 为根的子树中所有点的点权都增加 a . 询问某个节点 x 到根的路径中所有 ...