题意:
给定一个n个点,m条边的无向图。有q条有向路线分别从si到达ti。 如今你要给无向图的每条边分配一个方向。问是否存在一种分配答案使得全部路线都可以被知足。
\(1≤n,m,q≤2×10^5\)c++
这道题初看上去没什么思路,
可是咱们仔细想一想能够发现若一个点到另外一个点有两条彻底不一样的路径的话,
咱们可让一条正向,一条反向,
不管怎样的询问都无妨。
哇!
”一个点到另外一个点有两条彻底不一样的路径“?
这不是边双连通份量吗?
全部在同一个边双的询问就不用考虑了。
可是边双之间的路径呢?
怎么办?
同一个边双里没有什么做用,
咱们干脆缩点,
以后就成了森林。
询问就剩两种状况:数组
1.不在同一颗树中,直接No;
2.在同一棵树中:看看每一条边是否是既要求正向,又要求反向。
这个树上差分搞一下就好了。
两个数组,
一个正向,一个反向。spa
#include<bits/stdc++.h> using namespace std; const int N=2e5+6; int n,m,q; int t1,t2,cnt=1,f[N],v[N],dfn[N],low[N],head[N],num2[N]; int deep=0,d[N],top[N],son[N],siz[N],book[N],num[N]; int f2[N],id[N],fa[N],head2[N],tot=0,cnt2=0,LCA; map<int,int> ha[N]; struct edge{int nxt,to;}e[N<<1],g[N<<1]; inline int read(){ int T=0,F=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();} while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar(); return F*T; } inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;} inline void add2(int u,int v){g[++cnt2].nxt=head2[u],g[cnt2].to=v,head2[u]=cnt2;} int getf(int x){return fa[x]==x?x:fa[x]=getf(fa[x]);} void merge(int x,int y){ x=getf(x),y=getf(y); if(x==y) return; fa[x]=y; } void tarjan(int u,int fr){ dfn[u]=low[u]=++deep; for(int i=head[u];i;i=e[i].nxt){ if(i==fr) continue; if(!dfn[e[i].to]) f[e[i].to]=u,tarjan(e[i].to,i^1),low[u]=min(low[u],low[e[i].to]); else low[u]=min(low[u],dfn[e[i].to]); } } void dfs(int x,int ff,int o){ f2[x]=ff,d[x]=d[ff]+1,siz[x]=1,id[x]=o; int maxt=0; for(int i=head2[x];i;i=g[i].nxt) if(g[i].to!=ff){dfs(g[i].to,x,o),siz[x]+=siz[e[i].to]; if(siz[maxt]<siz[g[i].to]) maxt=g[i].to;} son[x]=maxt; } void dfs2(int x,int topx){ top[x]=topx; if(son[x]) dfs2(son[x],topx); for(int i=head2[x];i;i=g[i].nxt) if(g[i].to!=f2[x]&&g[i].to!=son[x]) dfs2(g[i].to,g[i].to); } void dfs3(int x){ v[x]=1; for(int i=head2[x];i;i=g[i].nxt) if(g[i].to!=f2[x]) dfs3(g[i].to),num[x]+=num[g[i].to],num2[x]+=num2[g[i].to]; if(num[x]&&num2[x]){printf("No\n"); exit(0);} } int lca(int x,int y){ while(top[x]!=top[y]){ if(d[top[x]]<d[top[y]]) swap(x,y); x=f2[top[x]]; } if(d[x]>d[y]) swap(x,y); return x; } int main(){ n=read(),m=read(),q=read(); for(int i=1;i<=m;++i) t1=read(),t2=read(),add(t1,t2),add(t2,t1); for(int i=1;i<=n;++i){if(!dfn[i]) tarjan(i,0); fa[i]=i;} for(int i=1;i<=n;++i) if(f[i]&&low[i]>dfn[f[i]]) v[i]=1,ha[i][f[i]]=ha[f[i]][i]=1; for(int i=1;i<=n;++i) for(int j=head[i];j;j=e[j].nxt) if(ha[i].find(e[j].to)==ha[i].end()) merge(i,e[j].to); for(int i=1;i<=n;++i){ t1=getf(i); if(!v[i]) continue; if(!book[fa[i]]) ++tot,book[fa[i]]=tot; if(!book[fa[f[i]]]) ++tot,book[fa[f[i]]]=tot; add2(book[fa[i]],book[fa[f[i]]]),add2(book[fa[f[i]]],book[fa[i]]); } for(int i=1;i<=tot;++i) if(!id[i]) dfs(i,0,i),dfs2(i,i); for(int i=1;i<=q;++i){ t1=read(),t2=read(),t1=book[fa[t1]],t2=book[fa[t2]]; if(id[t1]!=id[t2]){printf("No\n"); return 0;} if(t1==t2) continue; LCA=lca(t1,t2),++num[t1],--num[LCA],++num2[t2],--num2[LCA]; } memset(v,0,sizeof(v)); for(int i=1;i<=tot;++i) if(!v[i]) dfs3(i); printf("Yes\n"); return 0; }