[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");
}

转载于:https://www.cnblogs.com/birchtree/p/11192706.html

[Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分)相关推荐

  1. bzoj 1123: [POI2008]BLO (tarjan求点双+树形DP)

    题目描述 传送门 题目大意:给出一个无向连通图,求删去一个点后有多少点对不连通. 题解 tarjan求点双,然后对于点双新建节点,并连接所有点双中的节点,形成一棵树后进行树形DP即可. 代码 #inc ...

  2. [BZOJ1123][POI2008]BLO(tarjan求点双+树形dp)

    题目描述 传送门 题目大意:给出一个n个点m条边的无向连通图,问去掉每一个点之后存在多少点对不连通. 题解 tarjan求点双联通分量,对于每一个点双建立一个虚拟的节点,然后将这个点双的所有节点都连接 ...

  3. 【POJ - 3352】Road Construction(Tarjan,边双连通分量)

    题干: It's almost summer time, and that means that it's almost summer construction time! This year, th ...

  4. UVA - 315 Network(tarjan求割点)

    题目链接:点击查看 题目大意:给出一个由n台电脑互相连接而成的网络系统,其中有一些电脑如果一旦损坏,则会造成整个网络出现缺口,导致某些地方无法互相连通,我们称这种电脑为关键点,题目需要求出有多少个关键 ...

  5. CF555E Case of Computer Network

    https://www.luogu.com.cn/problem/CF555E 首先发现边双内的点可以互相到达 所以先缩边双,然后原图变成一棵树 对于经过一条边的路径,只能有一个方向 所以可以统计每条 ...

  6. bzoj 2730: [HNOI2012]矿场搭建——tarjan求点双

    Description 煤矿工地可以看成是由隧道连接挖煤点组成的无向图.为安全起见,希望在工地发生事故时所有挖煤点的工人都能有一条出路逃到救援出口处.于是矿主决定在某些挖煤点设立救援出口,使得无论哪一 ...

  7. 图论 —— 图的连通性 —— Tarjan 求双连通分量

    [概念] 1.双连通分量:对于一个无向图,其边/点连通度大于1,满足任意两点之间,能通过两条或两条以上没有任何重复边的路到达的图,即删掉任意边/点后,图仍是连通的 2.分类: 1)点双连通图:点连通度 ...

  8. 学习有向图和无向图的强连通分量(基本概念+割点+点双联通分量+桥+边双连通分量+全套模板【Tarjan】)

    最近总是考到Tarjan,让我措手不及 基本概念 割点以及点双连通分量 Tarjan法求割点 推导过程 代码实现 Tarjan法求点双连通分量 推导过程 代码实现 有向图的Tarjan缩点 桥与边双连 ...

  9. The King’s Problem(tarjan求强连通分量缩点+匈牙利求有向无环图的最小路径覆盖)

    Link:http://acm.hdu.edu.cn/showproblem.php?pid=3861 The King's Problem Time Limit: 2000/1000 MS (Jav ...

最新文章

  1. jQuery中的closest()和parents()的差别
  2. ASP.NET页面缓存介绍
  3. python3 通过列表作为键 产生字典
  4. wiki维基百科上logo中字母的意思是什么?
  5. AVPlayer 之avcore模块
  6. 医学影像设备学_医学影像技术考研可选的六大院校
  7. 首次!海豚间像人类一样的交谈被水下麦克风记录
  8. 验证规则构建神器 FluentValidation.md
  9. webpackjsonp 还原_具有催化CO2还原性能的非贵金属配合物的配体设计
  10. 【警惕】大量未修复WebLogic WSAT组件RCE漏洞的主机被挖矿程序攻击
  11. 数据库---主要约束操作讲解
  12. ADSL宽带路由密码恢复经验详谈
  13. 【DEVOPS】SVN Server迁移 - 从VisualSvnServer到iF.SVNAdmin
  14. 自然语言处理基础技术之成分句法分析
  15. 使用opencv将16位深度图转灰度图
  16. 细菌完成图+比较基因组分析添好文
  17. 冰雪奇缘 --用爱铸就经典
  18. 编写名为censor的函数,用来把字符串中出现的每一处字母“foo”替换成“xxx”。例如,字符串“food fool”会变为“xxxd xxxl”。再不失清晰性的前提下程序越短越好
  19. 计算机排第三!新增的工学硕士博士学位
  20. 【解纠缠表示:图像增强】

热门文章

  1. 苹果手机(ios)拍照上传图片旋转90度问题---java后台处理
  2. 从 OSS 装载数据到 PostgreSQL
  3. ***PHP中error_reporting()用法详解(含codeigniter框架中屏蔽错误提示的解决方案)
  4. auto make System.map to C header file
  5. rocksdb和leveldb性能比较——写性能
  6. 2010版CCNP教材一览【图文】
  7. 集成ACEGI 进行权限控制
  8. “兰董”——激怒式Marketing,Market人底线何在?
  9. 在网上常听到说CEO CTO CIO CGO COO CFO什么什么..现在了解了一下..呵呵
  10. 转 openssl 建立服务器证书