CF555E Case of Computer Network
CF555E Case of Computer Network
题意
给你一个 \(n\) 个点 \(m\) 条边的简单无向图(无自环)。
给你 \(q\) 个点对 \((s_i,t_i)\),问是否存在一个给无向图定向的方案,使得 \(\forall i\),\(s_i\) 均能到达对应的 \(t_i\)。只需输出 Yes 或 No。
\(n,m,q \le 2 \times 10^5\)。
思路
对于一个边双,一定存在一个定向方案变成一个强连通分量。
所以缩掉边双,剩下一个树。
如果 \(s\) 和 \(t\) 不在一个边双里面,它们之间的树边方向就是唯一确定的。
可以使用树上差分标记,最后判断是否合法。
时间复杂度同阶的忽略掉就是 \(O(n \log n)\)(因为求 LCA 需要一个 \(\log\))。
code
不难写的,只是思维难度稍微有点高?洛谷评紫。可能蓝更好,不过是上位蓝。
#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace wing_heart {
constexpr int N=2e5+7;
int n,m,q;
struct pii {
int v,id;
};
vector<pii> to[N];
vector<int> tr[N];
int dfn[N],cnt;
int low[N];
int col[N],num;
int st[N],top;
void tarjan(int u,int fr) {
dfn[u] = low[u] = ++cnt;
st[++top]=u;
for(auto p : to[u]) {
int v=p.v, id=p.id;
if(id==fr) continue;
if(!dfn[v]) {
tarjan(v,id);
low[u]=min(low[u],low[v]);
} else {
low[u]=min(low[u],low[v]);
}
}
if(low[u] == dfn[u]) {
++num;
col[u]=num;
while(st[top]!=u) {
col[st[top]]=num;
--top;
}
--top;
}
}
int tg[N][2];
int stb[20][N];
int T[N];
void dfs(int u,int fa,int tx) {
T[u]=tx;
dfn[u]=++cnt;
stb[0][dfn[u]]=fa;
for(int v : tr[u]) if(v^fa) {
dfs(v,u,tx);
}
}
int stbmin(int x,int y) { return dfn[x]<dfn[y] ? x : y; }
int getlca(int u,int v) {
if(u==v) return u;
int mx=max(dfn[u],dfn[v]), mn=min(dfn[u],dfn[v])+1;
int k=__lg(mx-mn+1);
return stbmin(stb[k][mn],stb[k][mx-(1<<k)+1]);
}
bool ans=1;
void dfs2(int u,int fa) {
dfn[u]=1;
for(int v : tr[u]) if(v^fa) {
dfs2(v,u);
tg[u][0]+=tg[v][0];
tg[u][1]+=tg[v][1];
}
if(tg[u][0] && tg[u][1]) ans=0;
}
void main() {
sf("%d%d%d",&n,&m,&q);
rep(i,1,m) {
int u,v;
sf("%d%d",&u,&v);
to[u].push_back({v,i});
to[v].push_back({u,i});
}
// 求边双
rep(i,1,n) {
if(!dfn[i]) tarjan(i,0);
}
rep(i,1,n) {
for(auto p : to[i]) {
if(col[p.v]!=col[i]) tr[col[i]].push_back(col[p.v]);
}
}
// 预处理 dfs 序求 LCA
memset(dfn+1,0,sizeof(int)*num);
cnt=0;
rep(i,1,num) if(!dfn[i]) dfs(i,0,i);
int lg=__lg(num);
rep(k,1,lg) for(int i=1;i+(1<<k)-1<=num;++i) stb[k][i]=stbmin(stb[k-1][i],stb[k-1][i+(1<<(k-1))]);
// 处理询问
rep(i,1,q) {
int s,t;
sf("%d%d",&s,&t);
s=col[s], t=col[t];
if(T[s] != T[t]) {
ans=0;
continue;
}
int lca=getlca(s,t);
tg[s][0]++, tg[lca][0]--;
tg[t][1]++, tg[lca][1]--;
}
memset(dfn+1,0,sizeof(int)*num);
rep(i,1,num) if(!dfn[i]) dfs2(i,0);
if(ans) puts("Yes");
else puts("No");
}
}
int main() {
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("my.out","w",stdout);
#endif
wing_heart :: main();
}
本文来自博客园,作者:wing_heart,转载请注明原文链接:https://www.cnblogs.com/wingheart/p/19013430

浙公网安备 33010602011771号