Description
有一个n个点m条边的无向图,q个限制形如(x,y)。问能否找到一种给边定向的方式使得满足所有的限制可以从x到达y
Solution
复习一下图论的一些东西
一个边双内的点肯定可以定成内部互达的情况。缩完边双之后就可以得到一个森林,我们用打标记的方式在这个森林上乱搞就可以知道是否存在两个限制它们产生了冲突。
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
const int N=500005;
std:: stack <int> stack;
struct edge {int x,y,next;} ;
int bel[N],col[N];
bool vis[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
struct Graph {
edge e[N*2];
int ls[N],up[N],dw[N],edCnt;
int fa[N][21],dep[N],n;
void add_edge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {y,x,ls[y]}; ls[y]=edCnt;
}
void dfs1(int x) {
rep(i,1,20) fa[x][i]=fa[fa[x][i-1]][i-1];
for (int i=ls[x];i;i=e[i].next) {
if (e[i].y==fa[x][0]) continue;
fa[e[i].y][0]=x,dep[e[i].y]=dep[x]+1;
dfs1(e[i].y);
}
}
void dfs2(int x) {
vis[x]=1;
for (int i=ls[x];i;i=e[i].next) {
if (vis[e[i].y]) continue;
dfs2(e[i].y);
up[x]+=up[e[i].y];
dw[x]+=dw[e[i].y];
}
}
int get_lca(int x,int y) {
if (dep[x]<dep[y]) std:: swap(x,y);
drp(i,20,0) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if (x==y) return x;
drp(i,20,0) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
void solve(int q) {
rep(i,1,n) if (!dep[i]) {
dep[i]=1; dfs1(i);
}
rep(i,1,q) {
int x=read(),y=read();
if (col[x]!=col[y]) {
puts("No"); return ;
}
x=bel[x],y=bel[y];
int lca=get_lca(x,y);
up[x]++,up[lca]--;
dw[y]++,dw[lca]--;
}
rep(i,1,n) if (!vis[i]) dfs2(i);
rep(i,1,n) if (up[i]&&dw[i]) {
puts("No"); return ;
} puts("Yes");
}
} G;
edge e[N*2];
int dfn[N],low[N];
int ls[N],edCnt,tot;
void add_edge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {y,x,ls[y]}; ls[y]=edCnt;
}
void dfs(int x,int from) {
dfn[x]=low[x]=++dfn[0];
col[x]=col[0];
stack.push(x),vis[x]=1;
for (int i=ls[x];i;i=e[i].next) {
if ((i^1)==from) continue;
if (!dfn[e[i].y]) {
dfs(e[i].y,i);
low[x]=std:: min(low[x],low[e[i].y]);
} else if (vis[e[i].y]) low[x]=std:: min(low[x],dfn[e[i].y]);
}
if (dfn[x]<=low[x]) {
int y=0; tot++;
while (y!=x) {
y=stack.top(),stack.pop();
bel[y]=tot; vis[y]=0;
}
}
}
int main(void) {
// freopen("data.in","r",stdin);
int n=read(),m=read(),q=read();
edCnt=1;
rep(i,1,m) add_edge(read(),read());
rep(i,1,n) if (!dfn[i]) {
col[0]++; dfs(i,0);
}
for (int i=2;i<=edCnt;i+=2) {
if (bel[e[i].x]!=bel[e[i].y]) {
G.add_edge(bel[e[i].x],bel[e[i].y]);
}
}
G.n=tot;
G.solve(q);
return 0;
}