codeforces555E
Case of Computer Network
Andrewid the Android is a galaxy-known detective. Now he is preparing a defense against a possible attack by hackers on a major computer network.
In this network are n vertices, some pairs of vertices are connected by m undirected channels. It is planned to transfer q important messages via this network, the i-th of which must be sent from vertex si to vertex di via one or more channels, perhaps through some intermediate vertices.
To protect against attacks a special algorithm was developed. Unfortunately it can be applied only to the network containing directed channels. Therefore, as new channels can't be created, it was decided for each of the existing undirected channels to enable them to transmit data only in one of the two directions.
Your task is to determine whether it is possible so to choose the direction for each channel so that each of the q messages could be successfully transmitted.
Input
The first line contains three integers n, m and q (1 ≤ n, m, q ≤ 2·105) — the number of nodes, channels and important messages.
Next m lines contain two integers each, vi and ui (1 ≤ vi, ui ≤ n, vi ≠ ui), that means that between nodes vi and ui is a channel. Between a pair of nodes can exist more than one channel.
Next q lines contain two integers si and di (1 ≤ si, di ≤ n, si ≠ di) — the numbers of the nodes of the source and destination of the corresponding message.
It is not guaranteed that in it initially possible to transmit all the messages.
Output
If a solution exists, print on a single line "Yes" (without the quotes). Otherwise, print "No" (without the quotes).
Examples
4 4 2
1 2
1 3
2 3
3 4
1 3
4 2
Yes
3 2 2
1 2
3 2
1 3
2 1
No
3 3 2
1 2
1 2
3 2
1 3
2 1
Yes
Note
In the first sample test you can assign directions, for example, as follows: 1 → 2, 1 → 3, 3 → 2, 4 → 3. Then the path for for the first message will be 1 → 3, and for the second one — 4 → 3 → 2.
In the third sample test you can assign directions, for example, as follows: 1 → 2, 2 → 1, 2 → 3. Then the path for the first message will be 1 → 2 → 3, and for the second one — 2 → 1.
简要题意:给出一个无向图,给出q个询问S,T表示从S走到T。
问能否给这张图的边定向,使得满足q个询问
sol:因为是无向图,所以在同一个强联通分量中是两两可以随意到达,然后可以搞成一棵树,树上可以差分一下,两个数组p0,p1,S位置p0++,T位置p1++,Lca处p0--,p1--,看看是否有一个点既有p0又有p1就No了
/*
¼òÒªÌâÒ⣺¸ø³öÒ»¸öÎÞÏòͼ£¬¸ø³öq¸öѯÎÊS£¬T±íʾ´ÓS×ßµ½T¡£
ÎÊÄÜ·ñ¸øÕâÕÅͼµÄ±ß¶¨Ïò£¬Ê¹µÃÂú×ãq¸öѯÎÊ
*/
#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll s=; bool f=; char ch=' ';
while(!isdigit(ch)) {f|=(ch=='-'); ch=getchar();}
while(isdigit(ch)) {s=(s<<)+(s<<)+(ch^); ch=getchar();}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<) {putchar('-'); x=-x;}
if(x<) {putchar(x+''); return;}
write(x/); putchar((x%)+'');
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int N=,M=;
int n,m,Q;
int tot=,Next[M],to[M],head[N];
struct Ques{int S,T;}qq[N];
inline void Link(int x,int y)
{
Next[++tot]=head[x]; to[tot]=y; head[x]=tot;
}
int cnt=,dfn[N],low[N],top=,Sta[N],now=,Bel[N];
bool ins[N];
inline void tarjan(int x,int fat)
{
int i;
bool bo=;
dfn[x]=low[x]=++cnt; Sta[++top]=x; ins[x]=;
for(i=head[x];i;i=Next[i])
{
if(to[i]==fat&&bo) {bo=; continue;}
if(!dfn[to[i]])
{
tarjan(to[i],x); low[x]=min(low[x],low[to[i]]);
}
else if(ins[to[i]]) low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x])
{
int oo=; now++;
while(oo!=x)
{
oo=Sta[top--]; Bel[oo]=now; ins[oo]=;
}
}
}
vector<int>E[N];
#define PB push_back
int fa[N];
inline int gf(int x)
{
return (fa[x]==x)?(x):(fa[x]=gf(fa[x]));
}
int Dep[N],ff[N][];
inline void dfs(int x,int fat)
{
int i;
for(i=;i<E[x].size();i++) if(E[x][i]!=fat)
{
Dep[E[x][i]]=Dep[x]+; ff[E[x][i]][]=x; dfs(E[x][i],x);
}
}
inline int ask_lca(int x,int y)
{
int i;
if(Dep[x]<Dep[y]) swap(x,y);
for(i=;~i;i--) if(Dep[ff[x][i]]>=Dep[y]) x=ff[x][i];
if(x==y) return x;
for(i=;~i;i--) if(ff[x][i]!=ff[y][i]) x=ff[x][i],y=ff[y][i];
return ff[x][];
}
int path[N][];
bool Vis[N];
inline void dfss(int x,int fat)
{
int i;
Vis[x]=;
for(i=;i<E[x].size();i++)
{
int V=E[x][i]; if(V==fat) continue;
dfss(V,x);
path[x][]+=path[V][]; path[x][]+=path[V][];
}
}
int main()
{
// freopen("codeforces555E.in","r",stdin);
int i,j,x,y;
R(n); R(m); R(Q);
for(i=;i<=m;i++)
{
R(x); R(y); Link(x,y); Link(y,x);
}
for(i=;i<=Q;i++) {R(qq[i].S); R(qq[i].T);}
for(i=;i<=n;i++) if(!dfn[i]) tarjan(i,);
// cout<<"now="<<now<<endl;
// for(i=1;i<=n;i++) cout<<i<<' '<<Bel[i]<<endl;
// puts("");
for(i=;i<=now;i++) fa[i]=i;
for(i=;i<=n;i++)
{
for(j=head[i];j;j=Next[j])
{
int o1=gf(Bel[i]),o2=gf(Bel[to[j]]);
if(o1==o2) continue;
E[Bel[i]].PB(Bel[to[j]]); E[Bel[to[j]]].PB(Bel[i]); fa[o1]=o2;
}
}
for(i=;i<=now;i++) if(!Dep[i]) {Dep[i]=; dfs(i,);}
// for(i=1;i<=now;i++) cout<<i<<' '<<Dep[i]<<endl;
// puts("");
for(i=;i<=;i++) for(j=;j<=now;j++) ff[j][i]=ff[ff[j][i-]][i-];
// for(i=1;i<=now;i++) cout<<i<<' '<<ff[i][0]<<endl;
// puts("");
for(i=;i<=Q;i++)
{
int S=Bel[qq[i].S],T=Bel[qq[i].T];
// cout<<S<<' '<<gf(S)<<' '<<T<<' '<<gf(T)<<endl;
if(gf(S)!=gf(T)) return puts("No"),;
int lca=ask_lca(S,T);
// cout<<S<<' '<<T<<' '<<"lca="<<lca<<endl;
path[S][]++; path[lca][]--; path[T][]++; path[lca][]--;
}
// puts("");
// for(i=1;i<=now;i++) cout<<i<<' '<<path[i][0]<<' '<<path[i][1]<<endl;
for(i=;i<=now;i++) if(!Vis[i]) dfss(i,);
for(i=;i<=Q;i++)
{
int S=Bel[qq[i].S],T=Bel[qq[i].T]; if(S==T) continue;
if((path[S][]&&path[S][])||(path[T][]&&path[T][])) return puts("No"),;
}
puts("Yes");
return ;
}
/*
Input
4 4 2
1 2
1 3
2 3
3 4
1 3
4 2
Output
Yes Input
3 2 2
1 2
3 2
1 3
2 1
Output
No Input
3 3 2
1 2
1 2
3 2
1 3
2 1
Output
Yes
*/
codeforces555E的更多相关文章
随机推荐
- 10.使用du将文件按大小进行排序
按G进行排序du -sh * | grep G | sort -nr
- Java并发(思维导图)【待评估、删除】
1, 2, 3,常用函数 Semaphore import java.util.concurrent.Semaphore;Semaphore name=new Semaphore(n); name.a ...
- iview表单验证数字
验证输入字符串必须为数字 html: <FormItem label="兑换积分:" prop="exchangeIntegral"> <In ...
- Google开源项目风格指南
Google开源项目风格指南 来源 https://github.com/zh-google-styleguide/zh-google-styleguide Google 开源项目风格指南 (中文版) ...
- sql server 语句书写注意事项
1 Between在某些时候比IN 2 在必要是对全局或者局部临时表创建索引,有时能够提高速度,但不是一定会这样,因为索引也耗费大量的资源.他的创建同是实际表一样 3 尽量少用视图,它的效率低.对视 ...
- $(selector).each() 和$each() 的区别
今天在做项目的时候, 后台数据需要循环遍历出来, 想到each, 结果,竟然不记得语法了 现在来回顾一下,而搜索了一下,竟然发现有两种each 一种就是$(selector).each() ...
- vim编辑命令
vi命令 命令模式: yy:复制 光标所在的这一行 4yy:复制 光标所在行开始向下的4行 p: 粘贴 dd:剪切 光标所在的这一行 2dd:剪切 光标所在行 向下 2行 D:从当前的光标开始剪切,一 ...
- 命令ls按文件大小来排序
有时候我们想按照文件的大小来排序,一直忘记,为此特记下如下操作 按照文件所占的大小从大开始排列 # ls -lS total 64 -rw-r--r-- 1 root root 55895 Nov 5 ...
- git core.autocrlf配置说明
格式化 格式化是许多开发人员在协作时,特别是在跨平台情况下,遇到的令人头疼的细小问题. 由于编辑器的不同或者Windows程序员在跨平台项目中的文件行尾加入了回车换行符, 一些细微的空格变化会不经意地 ...
- 蓝桥杯入门——1.Fibonacci数列
问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. 输入格式 输入包含一个整数n ...