传送门

题意:给出$N$个点、$M$条无向边的图,现在你需要给它定向,并满足$Q$个条件:每个条件形如$(x_i,y_i)$,表示定向之后需要存在路径从$x_i$走向$y_i$。问每条边是否都有唯一定向方式。$N,M,Q \leq 10^5$


图论总是涉及的算法不难,但是就是脑子生锈想不出来

可以知道一个边双联通分量里面的所有边的方向都是一定不能确定的,因为如果存在一种方式满足所有条件,将这个边双联通分量里的所有边取反之后也一定满足条件。所以我们只需要考虑割边。

不妨在原图中找到一棵树,这棵树上必定包含所有的割边。通过差分将非割边打上标记,我们就可以通过在新的树上求$LCA$加上差分对所有边向上还是向下打好标记,最后$dfs$求出答案即可。

实际上还可以并查集,但是并查集写炸了qwq

注意重边,还要注意图不连通的情况

 #include<bits/stdc++.h>
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MAXN = ;
struct Edge{
int end , upEd;
}Ed[MAXN << ];
int N , M , cntEd = , head[MAXN] , dep[MAXN] , up[MAXN] , down[MAXN] , can[MAXN] , jump[MAXN][];
char ans[MAXN];
bool vis[MAXN]; inline void addEd(int a , int b){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
head[a] = cntEd;
} void dfs(int x , int fa){
jump[x][] = fa;
dep[x] = dep[fa] + ;
for(int i = ; i <= ; i++)
jump[x][i] = jump[jump[x][i - ]][i - ];
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!dep[Ed[i].end])
dfs(Ed[i].end , x);
else
if(dep[Ed[i].end] > dep[x]){
can[Ed[i].end]++;
can[x]--;
}
} void Dfs(int x){
vis[x] = ;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(dep[Ed[i].end] == dep[x] + && !vis[Ed[i].end]){//不加vis判断会炸!!!
Dfs(Ed[i].end);
if(can[Ed[i].end] == )
if((i & ) && up[Ed[i].end] || !(i & ) && down[Ed[i].end])
ans[i >> ] = 'R';
else
if(!(i & ) && up[Ed[i].end] || (i & ) && down[Ed[i].end])
ans[i >> ] = 'L';
up[x] += up[Ed[i].end];
down[x] += down[Ed[i].end];
can[x] += can[Ed[i].end];
}
} inline int jumpToLCA(int x , int y){
if(dep[x] < dep[y])
swap(x , y);
for(int i = ; i >= ; i--)
if(dep[x] - ( << i) >= dep[y])
x = jump[x][i];
if(x == y)
return x;
for(int i = ; i >= ; i--)
if(jump[x][i] != jump[y][i]){
x = jump[x][i];
y = jump[y][i];
}
return jump[x][];
} int main(){
#ifdef LG
freopen("4652.in" , "r" , stdin);
freopen("4652.out" , "w" , stdout);
#endif
N = read();
M = read();
for(int i = ; i <= M ; i++){
int a = read() , b = read();
addEd(a , b);
addEd(b , a);
}
for(int i = ; i <= N ; i++)
if(!dep[i])
dfs(i , );
for(int Q = read() ; Q ; Q--){
int a = read() , b = read() , t = jumpToLCA(a , b);
up[a]++;
up[t]--;
down[t]--;
down[b]++;
}
memset(ans , 'B' , sizeof(ans));
for(int i = ; i <= N ; i++)
if(!vis[i])
Dfs(i);
for(int i = ; i <= M ; i++)
cout << ans[i];
return ;
}

Luogu4652 CEOI2017 One-Way Streets 树上差分的更多相关文章

  1. loj2480 [CEOI2017]One-Way Streets 边双+树上差分

    边双无法确定 缩完边双就是一棵树 树上差分随意弄一下吧... #include <vector> #include <cstdio> #include <cstring& ...

  2. 【BZOJ-4326】运输计划 树链剖分 + 树上差分 + 二分

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 703  Solved: 461[Submit][Status] ...

  3. [luogu P3128][USACO15DEC]Max Flow [LCA][树上差分]

    题目描述 Farmer John has installed a new system of  pipes to transport milk between the  stalls in his b ...

  4. 树上差分 (瞎bb) [树上差分][LCA]

    做noip2015的运输计划写了好久好久写不出来   QwQ 于是先来瞎bb一下树上差分    混积分 树上差分有2个常用的功能: (1)记录从点i到i的父亲这条路径走过几次 (2)将每条路径(s,t ...

  5. [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)

    今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...

  6. 【NOIP2016】【LCA】【树上差分】【史诗级难度】天天爱跑步

    学弟不是说要出丧题吗>>所以我就研究了1天lca又研究了1天tj然后研究了一天天天爱跑步,终于写了出来.(最后的平均用时为240ms...比学弟快了1倍...) 题意:给你颗树,然后有m个 ...

  7. BZOJ_4238_电压_树上差分+dfs树

    BZOJ_4238_电压_树上差分+dfs树 Description 你知道Just Odd Inventions社吗?这个公司的业务是“只不过是奇妙的发明(Just Odd Inventions)” ...

  8. BZOJ_3307_雨天的尾巴_线段树合并+树上差分

    BZOJ_3307_雨天的尾巴_线段树合并 Description N个点,形成一个树状结构.有M次发放,每次选择两个点x,y 对于x到y的路径上(含x,y)每个点发一袋Z类型的物品.完成 所有发放后 ...

  9. [GXOI/GZOI2019]旧词(树上差分+树剖)

    前置芝士:[LNOI2014]LCA 要是这题放HNOI就好了 原题:\(\sum_{l≤i≤r}dep[LCA(i,z)]\) 这题:\(\sum_{i≤r}dep[LCA(i,z)]^k\) 对于 ...

随机推荐

  1. python之装饰器(函数)

    1. 装饰器 遵循的原则: 开闭原则:   对功能的扩展开放 对代码的修改是封闭 # 通用装饰器写法 # 存在的意义: 在不破坏原有函数和原有函数调用的基础上,给函数添加新的功能. def wrapp ...

  2. Apex 的异常处理

    Apex 中的异常处理 在 Apex 中,和其他语言类似,对于异常处理通常使用 try.catch.finally.throw 等关键字. 对于每一个 try 代码段,必须要有至少一个 catch 或 ...

  3. linux(乌班图)修改apt下载源

    有时候会出现乌班图系统刚安装,无法使用apt下载安装软件工具,此时需要修改apt下载源. 1.进入/etc/apt/目录下  2.备份sources.list文件(如果不在root用户下,需在前面加s ...

  4. SQL Server 2005详细安装过程及配置

    说明:个人感觉SQL Server 2005是目前所有的SQL Server版本当中最好用的一个版本了,原因就是这个版本比起其它版本来说要安装简单,操作简便,只可惜这个版本只能在Windows7或者低 ...

  5. MVC| NuGet安装相关工具包

    ----------------------------------------------Ninject----------------------------------------------- ...

  6. EntityFramework Code-First 简易教程(四)-------继承策略

    在前篇CodeFirst类型约定中,我们在数据库中为每一个模型类创建一个表,但是有个问题,我们可以设计出带继承关系的模型类,即面向对象编程既有“has a”(表示类继承)也有“is a”(表示类包含) ...

  7. Tell Me About Yourself Example 1

    Tell Me About Yourself Employers ask this question because they want to know you have the relevant e ...

  8. Flume-1.8.0_部署与常用案例

    该文章是基于 Hadoop2.7.6_01_部署 进行的 Flume官方文档:FlumeUserGuide 常见问题:记flume部署过程中遇到的问题以及解决方法(持续更新) 1. 前言 在一个完整的 ...

  9. system函数的应用

    system函数的两个简单应用 1.调用cmd命令.例:(打开计算器) #include <stdlib.h> int main() { system("calc"); ...

  10. ActivityThread main

    public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Ac ...