其他分享
首页 > 其他分享> > 题解 CF1707C【DFS Trees】

题解 CF1707C【DFS Trees】

作者:互联网

因为所有边权两两不同,所以 MST 是唯一的,我们把 MST 上的边标记出来。

我们知道对图进行 DFS 后,只有树边和返祖边两类边。要使得 MST 上的边均为树边,则不在 MST 上的边只能为返祖边。也就是说,不在 MST 上的边在当前根下必须是祖先后代关系。

至此,原问题转化为:判断每个节点作为根时,所有非 MST 边的两个点是否都是祖先后代关系。

我们可以随便找一个点当根,把每条非 MST 边两侧子树每个点的值加一(只有在这些点当根时才是祖先后代关系),然后判断每个点的值是否等于 \(m-n+1\) 即可。具体实现方法可以使用树上差分。

时间复杂度 \(\mathcal O(n\log n)\)。

// Problem: C. DFS Trees
// Contest: Codeforces - Codeforces Round #808 (Div. 1)
// URL: https://codeforces.com/contest/1707/problem/C
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

//By: OIer rui_er
#include <bits/stdc++.h>
#define rep(x,y,z) for(int x=(y);x<=(z);x++)
#define per(x,y,z) for(int x=(y);x>=(z);x--)
#define debug printf("Running %s on line %d...\n",__FUNCTION__,__LINE__)
#define fileIO(s) do{freopen(s".in","r",stdin);freopen(s".out","w",stdout);}while(false)
using namespace std;
typedef long long ll;
const int N = 2e5+5;

int n, m, vis[N], fa[N][20], dis[N], s[N];
vector<tuple<int, int> > e;
vector<int> t[N];
template<typename T> void chkmin(T& x, T y) {if(x > y) x = y;}
template<typename T> void chkmax(T& x, T y) {if(x < y) x = y;}
struct Dsu {
	int fa[N];
	void init(int x) {rep(i, 1, x) fa[i] = i;}
	int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
	bool merge(int x, int y) {
		int u = find(x), v = find(y);
		if(u == v) return 0;
		fa[u] = v;
		return 1;
	}
}dsu;
void kruskal() {
	dsu.init(n);
	rep(i, 0, m-1) {
		int u = get<0>(e[i]), v = get<1>(e[i]);
		if(dsu.merge(u, v)) {
			vis[i] = 1;
			t[u].push_back(v);
			t[v].push_back(u);
		}
	}
}
void dfs1(int u, int f) {
	fa[u][0] = f;
	dis[u] = dis[f] + 1;
	rep(i, 1, 19) fa[u][i] = fa[fa[u][i-1]][i-1];
	for(int v : t[u]) if(v != f) dfs1(v, u);
}
int LCA(int u, int v) {
	if(dis[u] < dis[v]) swap(u, v);
	per(i, 19, 0) if(dis[fa[u][i]] >= dis[v]) u = fa[u][i];
	if(u == v) return u;
	per(i, 19, 0) if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
	return fa[u][0];
}
void dfs2(int u, int f) {
	s[u] += s[f];
	for(int v : t[u]) if(v != f) dfs2(v, u);
}

int main() {
	scanf("%d%d", &n, &m);
	rep(i, 0, m-1) {
		int u, v;
		scanf("%d%d", &u, &v);
		e.emplace_back(u, v);
	}
	kruskal();
	dfs1(1, 0);
	rep(i, 0, m-1) {
		if(!vis[i]) {
			int u = get<0>(e[i]), v = get<1>(e[i]);
			int lca = LCA(u, v);
			if(dis[u] > dis[v]) swap(u, v);
			if(lca == u) {
				++s[1], ++s[v];
				int p = v;
				per(j, 19, 0) if(dis[fa[p][j]] > dis[u]) p = fa[p][j];
				--s[p];
			}
			else ++s[u], ++s[v];
		}
	}
	dfs2(1, 0);
	rep(i, 1, n) putchar(s[i]==m-n+1?'1':'0');
	puts("");
	return 0;
}

标签:int,题解,rep,MST,Trees,CF1707C,fa,void,dis
来源: https://www.cnblogs.com/ruierqwq/p/CF-1707C.html