題意:
給定一個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; }