## Luogu2860 [USACO06JAN]冗余路径Redundant Paths

$$\verb|Luogu2860 [USACO06JAN]冗余路径Redundant Paths|$$

$$1\leq n\leq5000,\ n-1\leq m\leq10^4$$

tarjan

$$lca(u,\ v)$$$$root$$ ，将会消去两个叶节点，否则只会消去一个叶节点，因此每次选择 $$lca(u,\ v)$$$$root$$ 的两个点，答案即为 $$叶节点的个数\lfloor\frac{\verb|叶节点的个数|+1}{2}\rfloor$$

#include <bits/stdc++.h>
using namespace std;

#define nc getchar()
const int maxn = 5010;
int n, m, tot, h[maxn], bl[maxn], dfn[maxn], low[maxn], deg[maxn]; bool vis[maxn], cut[maxn << 1];
struct edges {
int nxt, to;
edges(int x = 0, int y = 0) : nxt(x), to(y) {}
} e[maxn << 1];

int x = 0; char c = nc;
while (c < 48) c = nc;
while (c > 47) x = x * 10 + c - 48, c = nc;
return x;
}

void addline(int u, int v) {
static int cnt = 1;
e[++cnt] = edges(h[u], v), h[u] = cnt;
}

void tarjan(int u, int f) {
static int now;
dfn[u] = low[u] = ++now;
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!dfn[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (dfn[u] < low[v]) cut[i] = cut[i ^ 1] = 1;
} else if (v != f) {
low[u] = min(low[u], dfn[v]);
}
}
}

void dfs(int u) {
vis[u] = 1, bl[u] = tot;
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (!cut[i] && !vis[v]) dfs(v);
}
}

int main() {
for (int i = 1; i <= m; i++) {
}
tarjan(1, 0);
for (int i = 1; i <= n; i++) {
if (!vis[i]) tot++, dfs(i);
}
for (int u = 1; u <= n; u++) {
for (int i = h[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (bl[u] != bl[v]) deg[bl[v]]++;
}
}
int ans = 0;
for (int i = 1; i <= tot; i++) {
ans += deg[i] == 1;
}
printf("%d", (ans + 1) >> 1);
return 0;
}

0条评论