题目传送门

题目大意

给出一个\(n\)个点\(m\)条边的无向图,有\(q\)次有向点对\((s,t)\),问是否存在一种方法定向每条边使得每个点对可以\(s\to t\)。

\(n,m,q\le 2\times 10^5\)

思路

首先我们可以发现,一个边双连通分量里面肯定可以满足,因为任意两点之间都有两条及以上路径,于是可以一条过去,一条回来。于是,我们就可以先双连通分量缩点一下。

接着我们发现缩点完之后一定是个森林,因为如果存在环的话一定还可以缩点。那我们就可以用树上差分解决这个问题了。具体的话对于点对\((s,t)\),显然\(s\to lca(s,t)\)应该是向上的,\(lca(s,t)\to t\)应该是向下的。如果存在一个边既向上又向下那显然是矛盾的。

于是,我们就可以在\(\Theta(n\log n)\)的时间复杂度内解决这个问题。(求lca)

\(\texttt{Code}\)

#include <bits/stdc++.h>
using namespace std; #define Int register int
#define MAXN 400005 template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');} bool vis[MAXN << 1];
int n,m,q,s[MAXN],t[MAXN],sum[MAXN],dfn[MAXN],low[MAXN];
struct SolveTree{
int up;//表示边双连通分量有多少个
struct edge{
int v,nxt;
}e[MAXN << 1];
int toop = 1,Index,s1[MAXN],s2[MAXN],fa[MAXN][21],col[MAXN],dep[MAXN],head[MAXN];
void Add_Edge (int u,int v){
e[++ toop] = edge {v,head[u]};head[u] = toop;
e[++ toop] = edge {u,head[v]};head[v] = toop;
}
void dfs (int u,int par){
col[u] = Index,fa[u][0] = par,dep[u] = dep[par] + 1;
for (Int i = 1;i <= 20;++ i) fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (Int i = head[u];i;i = e[i].nxt){
int v = e[i].v;
if (v ^ par) dfs (v,u);
}
}
int LCA (int x,int y){
if (dep[x] < dep[y]) swap (x,y);
for (Int i = 20,dis = dep[x] - dep[y];~i;-- i) if (dis >> i & 1) x = fa[x][i];
if (x == y) return x;
else{
for (Int i = 20;~i;-- i) if (fa[x][i] ^ fa[y][i]) x = fa[x][i],y = fa[y][i];
return fa[x][0];
}
}
bool Remain(int u){
for (Int i = head[u];i;i = e[i].nxt){
int v = e[i].v;
if (v ^ fa[u][0]){
if (!Remain (v) || (s1[v] && s2[v])) return 0;
s1[u] += s1[v],s2[u] += s2[v];
}
}
return 1;
}
void Solve (){
for (Int i = 1;i <= up;++ i) if (!col[i]) ++ Index,dfs (i,0);
for (Int i = 1;i <= q;++ i){
int u = s[i],v = t[i];
if (col[u] != col[v]) return puts ("No"),void ();
else{
int w = LCA (u,v);
s1[u] ++,s1[w] --,s2[v] ++,s2[w] --;
}
}
for (Int i = 1;i <= up;++ i) if (dep[i] == 1 && !Remain (i)) return puts ("No"),void ();
puts ("Yes");
}
}T;
struct CutTree{
struct edge{
int v,nxt;
}e[MAXN << 1];
int top = 1,Index,head[MAXN],col[MAXN];
void Add_Edge (int u,int v){
e[++ top] = edge {v,head[u]};head[u] = top;
e[++ top] = edge {u,head[v]};head[v] = top;
}
int id;
void Tarjan (int u,int fa){
dfn[u] = low[u] = ++ id;
for (Int i = head[u];i;i = e[i].nxt) if (e[i].v ^ fa){
int v = e[i].v;
if (!dfn[v]){
Tarjan (v,u),low[u] = min (low[u],low[v]);
if (low[v] > dfn[u]) vis[i] = vis[i ^ 1] = 1;//vis[i]表示该边是不是割边
}
else low[u] = min (low[u],dfn[v]);
}
}
void dfs (int u){
col[u] = Index;
for (Int i = head[u],v;i;i = e[i].nxt) if (!col[v = e[i].v] && !vis[i]) dfs (v);
}
void build (){
read (n,m,q);
for (Int i = 1,u,v;i <= m;++ i) read (u,v),Add_Edge (u,v);
for (Int i = 1;i <= n;++ i) if (!dfn[i]) Tarjan (i,0);
for (Int i = 1;i <= n;++ i) if (!col[i]) ++ Index,dfs (i);T.up = Index;
for (Int i = 1;i <= n;++ i) for (Int j = head[i],v;j;j = e[j].nxt) if (col[v = e[j].v] > col[i]) T.Add_Edge (col[i],col[v]);
for (Int i = 1;i <= q;++ i){
read (s[i],t[i]),s[i] = col[s[i]],t[i] = col[t[i]];
if (s[i] == t[i]) i --,q --;
}
}
}G; signed main(){
G.build(),T.Solve();
return 0;
}

题解 CF555E Case of Computer Network的更多相关文章

  1. CF555E Case of Computer Network

    题面:https://www.luogu.com.cn/problem/CF555E 题意:给定一张\(n\)个点\(m\)条边的无向图. 给定\(q\)组有向点对\((s,t)\). 询问是否存在使 ...

  2. 「CF555E」 Case of Computer Network

    「CF555E」 Case of Computer Network 传送门 又是给边定向的题目(马上想到欧拉回路) 然而这个题没有对度数的限制,你想歪了. 然后又开始想一个类似于匈牙利的算法:我先跑, ...

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

    [Codeforces 555E]Case of Computer Network(Tarjan求边-双连通分量+树上差分) 题面 给出一个无向图,以及q条有向路径.问是否存在一种给边定向的方案,使得 ...

  4. (中等) CF 555E Case of Computer Network,双连通+树。

    Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible a ...

  5. 555E Case of Computer Network

    分析 一个连通块内的肯定不影响 于是我们先缩点 之后对于每个路径 向上向下分别开一个差分数组 如果两个数组同时有值则不合法 代码 #include<bits/stdc++.h> using ...

  6. Solution -「CF 555E」Case of Computer Network

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个点 \(m\) 条边的无向图,判断是否有给每条边定向的方案,使得 \(q\) 组有序点对 \((s,t)\) ...

  7. codeforces GYM 100114 J. Computer Network 无相图缩点+树的直径

    题目链接: http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” ...

  8. codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

    J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Des ...

  9. [J]computer network tarjan边双联通分量+树的直径

    https://odzkskevi.qnssl.com/b660f16d70db1969261cd8b11235ec99?v=1537580031 [2012-2013 ACM Central Reg ...

随机推荐

  1. linux使用xampp安装MediaWiki环境

    1.下载并安装xampp 下载xampp 在下载页面下载. 放置到相应目录 将xampp-linux-x64-5.6.3-0-installer.run文件复制到部署机器的/root目录下 安装 [r ...

  2. Java 中 常用API概述之 Math, Object, String,StringBuffer类,Arrays,Integer类

    Math Math类包含执行基本数字运算的方法,如基本指数,对数,平方根和三角函数. 与StrictMath类的一些数字方法不同,Math类的StrictMath所有Math都没有定义为返回比特位相同 ...

  3. SSE图像算法优化系列三十一:Base64编码和解码算法的指令集优化。

        一.基础原理 Base64是一种用64个Ascii字符来表示任意二进制数据的方法.主要用于将不可打印的字符转换成可打印字符,或者简单的说是将二进制数据编码成Ascii字符.Base64也是网络 ...

  4. MPI集群搭建

    高性能计算     ubantu下集群搭建 参考博客:https://blog.csdn.net/u012304016/article/details/52423738(尊重别人的知识产权),一些细节 ...

  5. Tricks

    由于本人着实有些菜,因此在此积累一些巧妙的 \(Tricks\) ,以备不时之需... 与其说是 \(Tricks\) 不如说是学习笔记?? 数学 组合数 常见的数列 斐波那契数列 图论 树论 \(P ...

  6. Identity角色管理三(编辑角色)

    因只有角色名能修改故继续使用创建角色的视图模型 using System.ComponentModel; using System.ComponentModel.DataAnnotations; na ...

  7. hyperf从零开始构建微服务(二)——构建服务消费者

    阅读目录 构建服务消费者 安装json rpc依赖 安装JSON RPC客户端 server配置 编写业务代码 编写服务消费者类 consumer配置 配置 UserServiceInterface ...

  8. Fastjson 1.2.22-24 反序列化漏洞分析(1)

    Fastjson 1.2.22-24 反序列化漏洞分析(1) 前言 FastJson是alibaba的一款开源JSON解析库,可用于将Java对象转换为其JSON表示形式,也可以用于将JSON字符串转 ...

  9. [第二篇]——Docker 架构之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 架构 Docker 包括三个基本概念: 镜像(Image):Docker 镜像(Image),就相当于是一个 root 文件系统.比如官方镜像 ubuntu:16.04 就包含了完整的一 ...

  10. 使用SQL SERVER存储过程实现历史数据迁移

    今天讲下软件开发中最常见的历史数据迁移方式.在讲迁移之前,先简单介绍下几个基本概念. 1.什么是历史数据迁移? 简单直白地说:就是将一些创建时间比较久而且不常用的历史数据,存储到另一个地方(可以是另一 ...