BZOJ1718: [Usaco2006 Jan] Redundant Paths 分離的路徑【邊雙模板】【傻逼題】
阿新 • • 發佈:2018-11-03
經典傻逼套路
就是把所有邊雙縮點之後葉子節點的個數
//Author: dream_maker #include<bits/stdc++.h> using namespace std; //---------------------------------------------- //typename typedef long long ll; //convenient for #define fu(a, b, c) for (int a = b; a <= c; ++a) #define fd(a, b, c) for (int a = b; a >= c; --a) #define fv(a, b) for (int a = 0; a < (signed)b.size(); ++a) //inf of different typename const int INF_of_int = 1e9; const ll INF_of_ll = 1e18; //fast read and write template <typename T> void Read(T &x) { bool w = 1;x = 0; char c = getchar(); while (!isdigit(c) && c != '-') c = getchar(); if (c == '-') w = 0, c = getchar(); while (isdigit(c)) { x = (x<<1) + (x<<3) + c -'0'; c = getchar(); } if (!w) x = -x; } template <typename T> void Write(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) Write(x / 10); putchar(x % 10 + '0'); } //---------------------------------------------- const int N = 1e5 + 10; struct Edge { int v, nxt; } E[N << 1]; int head[N], tot = 0, cnt_bcc = 0; int dfn[N], low[N], bel[N], ind = 0; stack<int> st; int n, m, fro[N], to[N], du[N]; void add(int u, int v) { E[++tot] = (Edge) {v, head[u]}; head[u] = tot; } void tarjan(int u, int fa) { dfn[u] = low[u] = ++ind; int k = 0; st.push(u); for (int i = head[u]; i; i = E[i].nxt) { int v = E[i].v; if (v == fa && !k) { k = 1; continue; } if (!dfn[v]) tarjan(v, u), low[u] = min(low[u], low[v]); else if (dfn[v] < dfn[u]) low[u] = min(low[u], dfn[v]); } if (low[u] == dfn[u]) { int now; ++cnt_bcc; do { now = st.top(); st.pop(); bel[now] = cnt_bcc; } while (now != u); } } int main() { #ifdef dream_maker freopen("input.txt", "r", stdin); #endif Read(n), Read(m); fu(i, 1, m) { Read(fro[i]), Read(to[i]); add(fro[i], to[i]); add(to[i], fro[i]); } fu(i, 1, n) if (!dfn[i]) tarjan(i, 0); fu(i, 1, m) { if (bel[fro[i]] != bel[to[i]]) { ++du[bel[fro[i]]]; ++du[bel[to[i]]]; } } int ans = 0; fu(i, 1, cnt_bcc) if (du[i] == 1) ++ans; Write((ans + 1) >> 1); return 0; }