您的位置:首页 > 其它

缩点+树上差分——Codeforces555E Case of Computer Network

2017-10-21 07:44 239 查看
题面:cf555e

简要题意:给出一个无向图,给出q个询问S,T表示从S走到T。问能否给这张图的边定向,使得满足q个询问

我们首先发现对于每一个边双连通分量,两两之间是可以随便到达的,包括去到外面的点。所以我们把边双都缩成一个点,这张图就变成了一棵树

对于树进行操作就简单多了,我们只要在S,T,LCA位置打上差分标记(S打向上,T打向下,LCA打消除),然后一遍dfs从下往上扫一遍,如果某个节点向下向上标记都存在的话,这条边就发生冲突了

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
using namespace std;
inline int read(){
int k=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}
return k*f;
}
int nedge=0,p[400010],nex[400010],head[400010];
int nedge1=0,p1[400010],nex1[400010],head1[400010];
int dfn[200010],low[200010],s[200010],d[200010],l[200010];
int n,m,q,cnt=0,Top=0,vis[200010];
int deep[200010],f[200010],son[200010],top[200010];
int fa[200010],rp[200010][2],b[200010];
inline int getfather(int x){return fa[x]==x?x:fa[x]=getfather(fa[x]);}
inline void addedge(int a,int b){
p[++nedge]=b;nex[nedge]=head[a];head[a]=nedge;
}
inline void addedge1(int a,int b){
p1[++nedge1]=b;nex1[nedge1]=head1[a];head1[a]=nedge1;
}
inline void tarjan(int x,int fa){
dfn[x]=low[x]=++cnt;
s[++Top]=x;bool r=1;b[x]=1;
for(int k=head[x];k;k=nex[k]){
if(p[k]==fa&&r){
r=0;continue;
}
if(!dfn[p[k]])tarjan(p[k],x),low[x]=min(low[x],low[p[k]]);
else if(b[p[k]])low[x]=min(low[x],dfn[p[k]]);
}
if(dfn[x]==low[x]){
d[0]++;int k=0;
do{
k=s[Top--];d[d[0]]++;l[k]=d[0];b[k]=0;
}while(k!=x);
}
}
inline void dfs(int x,int fat,int dep){
vis[x]=1;
deep[x]=dep;s[x]=1;f[x]=fat;
for(int k=head1[x];k;k=nex1[k])if(p1[k]!=fat){
dfs(p1[k],x,dep+1);s[x]+=s[p1[k]];
if(s[p1[k]]>s[son[x]])son[x]=p1[k];
}
}
inline void dfss(int x,int t){
top[x]=t;
if(son[x])dfss(son[x],t);
for(int k=head1[x];k;k=nex1[k])if(p1[k]!=f[x]&&p1[k]!=son[x])dfss(p1[k],p1[k]);
}
inline int lca(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
x=f[fx];fx=top[x];
}
if(deep[x]>deep[y])swap(x,y);return x;
}
inline void DFS(int x){
vis[x]=2;
for(int k=head1[x];k;k=nex1[k]){
int to=p1[k];
if(to==f[x])continue;
DFS(to);rp[x][0]+=rp[to][0];rp[x][1]+=rp[to][1];
}
if(rp[x][0]*rp[x][1]){puts("No");exit(0);}
}
int main()
{
n=read();m=read();q=read();
for(int i=1;i<=m;i++){
int x=read(),y=read();
addedge(x,y);addedge(y,x);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0);
for(int i=1;i<=d[0];i++)fa[i]=i;
for(int i=1;i<=n;i++)
for(int k=head[i];k;k=nex[k])if(l[i]!=l[p[k]]){
addedge1(l[i],l[p[k]]);
int fx=getfather(l[i]),fy=getfather(l[p[k]]);
fa[fx]=fy;
}
n=d[0];
for(int i=1;i<=n;i++)if(!vis[i]){
dfs(i,0,1);dfss(i,i);
}
for(int i=1;i<=q;i++){
int x=l[read()],y=l[read()];
int fx=getfather(x),fy=getfather(y);
if(fx!=fy)return puts("No")&0;
int LCA=lca(x,y);
rp[x][0]++;rp[y][1]++;rp[LCA][0]--;rp[LCA][1]--;
}
for(int i=1;i<=n;i++)if(vis[i]!=2)DFS(i);
puts("Yes");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces tarjan