题解 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