問題のコンピュータネットワークソリューションの事例
問題の意味:
点nが与えられるが、無向グラフの辺をmです。TIからのルートを通じて達するあり、Qの記事は、Siに。今、あなたは、各グラフを割り当てる自由エッジに方向性を与えたいです。Q.すべての答えが満たされているように流通ルートがあります。
\(1≤n、M、q≤2× 5 \ ^ 10)
初期のこの質問は何のアイデアを思わない、
あなたは別のポイントに2つの完全に異なるパスがある一点を見つけることができるかどうか、そして、我々はそれについて考え
、逆に、我々は前進をすることができます
に関係なく、お問い合わせはとにかくありますか。
うわー!
「もう一つのポイントは、2つの完全に異なるパスがありますか」?
これは、接続されているコンポーネントが行うダブルエッジではないでしょうか?
ダブル問い合わせの同じ側にすべてが考えられなかったでしょう。
しかし、それのダブルエッジ間のパス?
方法は?
何の二国間同じどのような役割は、ありません
、我々は単に、ポイントを縮小し
、それが森になりました。
私は2つのだけの状況を尋ねます:
1.同じツリー、直接ノーではない。
同じツリーで:各側面前方を見にのみ必要でなく、逆に必要とされていません。
木はライン上のいくつかの違いを行います。
二つの配列、
前進、逆。
#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;
}