[Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)
[Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)
题面
给出一个无向图,以及q条有向路径。问是否存在一种给边定向的方案,使得这q条路径都能被满足。(如果有一条边是从a->b),而经过它的路径是从b->a,那么久不满足)。只需要判断,不用输出方案。
分析
对于一个有向环,显然它可以允许各个方向的路径通过。所以我们只要把无向图里的边-双联通分量建成环,然后就不用考虑了。影响答案的只有桥。
所以我们求出所有桥,然后缩点,把图变成一棵树。
变成树之后考虑树上差分,给路径打标记。维护两个差分数组,一个表示向上的标记,一个表示向下的标记。对于一条路径u->v,只要up[u]++,up[lca(u,v)]--,down[v]++,down[lca(u,v)]--即可
注意原图可能不连通,所以如果路径的两端点不连通,直接输出No
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#define maxn 200000
#define maxlogn 22
#define maxm 200000
using namespace std;
int n,m,q;
struct graph{
struct edge{
int from;
int to;
int next;
}E[maxn*2+5];
int head[maxn+5];
int sz=1;
void add_edge(int u,int v){
sz++;
E[sz].from=u;
E[sz].to=v;
E[sz].next=head[u];
head[u]=sz;
}
}G,T;
int tim;
int is_bridge[maxm*2+5];
int low[maxn+5],dfn[maxn+5];
void tarjan(int x,int in_edge){//tarjan求出桥
dfn[x]=++tim;
low[x]=dfn[x];
for(int i=G.head[x];i;i=G.E[i].next){
int y=G.E[i].to;
if(!dfn[y]){
tarjan(y,i);
low[x]=min(low[x],low[y]);
if(dfn[x]<low[y]){
is_bridge[i]=is_bridge[i^1]=1;
}
}else if(i!=(in_edge^1)){
low[x]=min(low[x],dfn[y]);
}
}
}
int newn;
int vis[maxn+5],bel[maxn+5];
void get_e_dcc(int x,int mark){//求出边-双联通分量
vis[x]=1;
bel[x]=mark;
for(int i=G.head[x];i;i=G.E[i].next){
int y=G.E[i].to;
if(!vis[y]&&!is_bridge[i]){
get_e_dcc(y,mark);
}
}
}
void make_new_graph(){//缩点,把图变成树
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,0);
}
newn=0;
for(int i=1;i<=n;i++){
if(!vis[i]){
newn++;
get_e_dcc(i,newn);
}
}
for(int i=2;i<=G.sz;i++){
int u=G.E[i].from;
int v=G.E[i].to;
if(is_bridge[i]){
T.add_edge(bel[u],bel[v]);
// printf("%d %d\n",bel[u],bel[v]);
}
}
}
int log2n;
int deep[maxn+5];
int anc[maxn+5][maxlogn+5];
int tree_id[maxn+5];
void pre_lca(int x,int fa,int id){
tree_id[x]=id;
deep[x]=deep[fa]+1;
anc[x][0]=fa;
for(int i=1;i<=log2n;i++) anc[x][i]=anc[anc[x][i-1]][i-1];
for(int i=T.head[x];i;i=T.E[i].next){
int y=T.E[i].to;
if(y!=fa){
pre_lca(y,x,id);
}
}
}
int lca(int x,int y){
if(deep[x]<deep[y]) swap(x,y);
for(int i=log2n;i>=0;i--){
if(deep[anc[x][i]]>=deep[y]) x=anc[x][i];
}
if(x==y) return x;
for(int i=log2n;i>=0;i--){
if(anc[x][i]!=anc[y][i]){
x=anc[x][i];
y=anc[y][i];
}
}
return anc[x][0];
}
int upd[maxn+5],downd[maxn+5];//边向上和向下标记
void add_route(int x,int y){//树上差分
upd[x]++;
downd[y]++;
int lc=lca(x,y);
upd[lc]--;
downd[lc]--;
}
bool flag=true;
void get_sum(int x,int fa){
for(int i=T.head[x];i;i=T.E[i].next){
int y=T.E[i].to;
if(y!=fa){
get_sum(y,x);
upd[x]+=upd[y];
downd[x]+=downd[y];
}
}
if(upd[x]>0&&downd[x]>0) flag=false;
}
int main(){
int u,v;
scanf("%d %d %d",&n,&m,&q);
log2n=log2(n)+1;
for(int i=1;i<=m;i++){
scanf("%d %d",&u,&v);
G.add_edge(u,v);
G.add_edge(v,u);
}
make_new_graph();
for(int i=1;i<=newn;i++){
if(!deep[i]) pre_lca(i,0,i);//原图可能不联通,缩点后会变成森林
}
for(int i=1;i<=q;i++){
scanf("%d %d",&u,&v);
add_route(bel[u],bel[v]);
if(tree_id[bel[u]]!=tree_id[bel[v]]){
//如果不联通,那么直接输出No
printf("No\n");
return 0;
}
}
for(int i=1;i<=newn;i++){
if(deep[i]==1) get_sum(i,0);
}
if(flag) printf("Yes\n");
else printf("No\n");
}
[Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)的更多相关文章
- hdu 2460(tarjan求边双连通分量+LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2460 思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边 ...
- C++[Tarjan求点双连通分量,割点][HNOI2012]矿场搭建
最近在学图论相关的内容,阅读这篇博客的前提是你已经基本了解了Tarjan求点双. 由割点的定义(删去这个点就可使这个图不连通)我们可以知道,坍塌的挖煤点只有在割点上才会使这个图不连通,而除了割点的其他 ...
- codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点
J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Des ...
- (中等) CF 555E Case of Computer Network,双连通+树。
Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible a ...
- Tarjan求点双连通分量
概述 在一个无向图中,若任意两点间至少存在两条“点不重复”的路径,则说这个图是点双连通的(简称双连通,biconnected) 在一个无向图中,点双连通的极大子图称为点双连通分量(简称双连通分量,Bi ...
- 555E Case of Computer Network
分析 一个连通块内的肯定不影响 于是我们先缩点 之后对于每个路径 向上向下分别开一个差分数组 如果两个数组同时有值则不合法 代码 #include<bits/stdc++.h> using ...
- [J]computer network tarjan边双联通分量+树的直径
https://odzkskevi.qnssl.com/b660f16d70db1969261cd8b11235ec99?v=1537580031 [2012-2013 ACM Central Reg ...
- 「CF555E」 Case of Computer Network
「CF555E」 Case of Computer Network 传送门 又是给边定向的题目(马上想到欧拉回路) 然而这个题没有对度数的限制,你想歪了. 然后又开始想一个类似于匈牙利的算法:我先跑, ...
- Solution -「CF 555E」Case of Computer Network
\(\mathcal{Description}\) Link. 给定 \(n\) 个点 \(m\) 条边的无向图,判断是否有给每条边定向的方案,使得 \(q\) 组有序点对 \((s,t)\) ...
随机推荐
- linux Sersync 上配置客户端
1.安装 Rsync 并配置相关权限 在 SERSYNC 上配置 RSYNC 客户端相关权限认证: [root@SERSYNC /]# yum install rsync -y [root@SERSY ...
- VS 2019编辑含有资源文件.resx的项目时提示MSB3086 任务未能使用 SdkToolsPath 或注册表项找到“al.exe”
环境: Win10 X64, VS2019 错误提示: 错误 MSB3086 任务未能使用 SdkToolsPath“”或注册表项“HKEY_LOCAL_MACHINE\SOFTWARE\Micros ...
- bzoj 3569 DZY Loves Chinese II 随机算法 树上倍增
题意:给你一个n个点m条边的图,有若干组询问,每次询问会选择图中的一些边删除,删除之后问此图是否联通?询问之间相互独立.此题强制在线. 思路:首先对于这张图随便求一颗生成树,对于每一条非树边,随机一个 ...
- 二、冯式结构与哈佛结构及ARM处理器状态和处理器模式
2.1 冯式结构与哈佛结构 2.1.1 两者的区别 如果是独立的存储架构和信号通道那就是哈佛结构,否则就是冯式结构 结构与是否统一编址没有关系,也与 CPU 没有关系,与计算机的整体设计有关 CACH ...
- 去掉Tomcat网站地址栏的小猫图标
当我们打开CSDN等网站时,在地址栏前面就会出现红色的C状图标,如果在桌面新建此链接的快捷方式,则桌面图标也自动变为该地址栏ICO图标.在基于TOMCAT的BS应用或网站开发时,默认的图标为黄色的小猫 ...
- Nginx+lua_Nginx+GraphicsMagick来实现实时缩略图
1.安装GraphicsMagick cd /usr/local/src wget http://sourceforge.net/projects/graphicsmagick/files/graph ...
- R语言 Keras Training Flags
在需要经常进行调参的情况下,可以使用 Training Flags 来快速变换参数,比起直接修改模型参数来得快而且不易出错. https://tensorflow.rstudio.com/tools/ ...
- centos启动提示unexpected inconsistency RUN fsck MANUALLY
今天一台虚拟机背后的物理机故障了,主机迁移后变成了 read only filesystem.上面部署了很多长连接服务,没有关掉就直接reboot,报错: unexpected inconsisten ...
- SpringBoot整合MyBatis-Plus实现快速业务功能开发
概览:使用MybatisPlus和它的代码生成整合SpringBoot可以实现快速的业务功能开发,具体步骤如下 一.添加依赖 <dependency> <groupId>org ...
- 最佳实践 | 数据库迁云解决方案选型 & 流程全解析
Oracle是非常强大的综合数据库,但同时也存在一些劣势,比如由于采用集中式架构,无法很好地实现横向扩展,并且其稳定性依赖于硬件.出于架构升级.降低成本和云化等需求,越来越多的企业需要“去Oracle ...