1. 程式人生 > 其它 >#10098. 「一本通 3.6 例 1」分離的路徑

#10098. 「一本通 3.6 例 1」分離的路徑

技術標籤:強連通

如果葉子數(縮點後度為1的點)為1,則至少需要新增0條邊;
否則為(葉子數+1)/ 2;

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stack>
#define mem(a,b) memset(a,b,sizeof(a))
const int N = 202000;
typedef long long ll;
using namespace std;
struct node
{
    int u, v, net;
} e[N];
int head[
N], tot, pre[N]; void add(int u, int v) { e[++tot].v = v; e[tot].u = u; e[tot].net = head[u]; head[u] = tot; } int dfn[N], low[N], cnt, s[N], tp; int scc[N], sc; int sz[N], n, m, out[N]; void tarjan(int u, int f) { low[u] = dfn[u] = ++cnt; pre[u] = f; s[++tp] = u; for
(int i = head[u]; i; i = e[i].net) { int v = e[i].v; if (v == f) continue; if (!dfn[v]) { tarjan(v, u); low[u] = min(low[u], low[v]); } else low[u] = min(low[u], dfn[v]); } if (dfn[u] == low[
u]) { ++sc; while (s[tp] != u) { scc[s[tp]] = sc; --tp; } scc[s[tp]] = sc, --tp; } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); add(v, u); } // printf("---\n"); for (int i = 1; i <= n; i++) { if (!dfn[i]) tarjan(i, i); } for (int u = 1; u <= n; u++) { if (scc[u] != scc[pre[u]]) { sz[scc[u]]++; sz[scc[pre[u]]]++; } } int ans = 0; for (int i = 1; i <= sc; i++) { if (sz[i] == 1) ans++; } printf("%d\n", (ans + 1) >> 1); return 0; }