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号