POJ 3177 Redundant Paths
边双连通分量+缩点
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<algorithm> using namespace std; const int maxn = 10000 + 10; const int Maxn = 2 * 100000 + 10; int low[maxn]; int dfn[maxn]; int U[maxn], V[maxn]; int flag[maxn]; struct Edge { int from, to, id, ans; } edge[Maxn]; vector<int>G[maxn]; int N, M; int tmpdfn; int tot; int Start, End; int TxT[maxn]; int Belong[maxn]; int Block; int SUM[maxn]; void init() { for (int i = 0; i<maxn; i++) G[i].clear(); memset(low, 0, sizeof(low)); memset(dfn, 0, sizeof(dfn)); memset(flag, 0, sizeof(flag)); memset(TxT, 0, sizeof(TxT)); memset(SUM, 0, sizeof SUM); memset(Belong, 0, sizeof Belong); low[1] = dfn[1] = 1; tmpdfn = 0; tot = 0; Block = 0; } void AddEdge(int u, int v) { edge[tot].from = u; edge[tot].to = v; edge[tot].id = tot; edge[tot].ans = 0; G[u].push_back(tot); tot++; edge[tot].from = v; edge[tot].to = u; edge[tot].id = tot; edge[tot].ans = 0; G[v].push_back(tot); tot++; } int Tarjan(int u, int id) { tmpdfn++; int lowu = dfn[u] = tmpdfn; for (int i = 0; i<G[u].size(); i++) { int B = G[u][i]; if (!dfn[edge[B].to]) { int lowv = Tarjan(edge[B].to, edge[B].id); lowu = min(lowu, lowv); if (lowv >= dfn[u]) { if (lowv>dfn[u]) edge[B].ans = 1; } } else if (dfn[edge[B].to]) { if (edge[B].id / 2 == id / 2) continue; lowu = min(lowu, dfn[edge[B].to]); } } low[u] = lowu; return lowu; } void Dfs(int x, int y) { int XZ = 0; for (int i = 0; i<G[x].size(); i++) { int B = G[x][i]; if (!flag[edge[B].id / 2]) { XZ = 1; flag[edge[B].id / 2] = 1; TxT[edge[B].to] = 1; Belong[edge[B].from] = Block; Belong[edge[B].to] = Block; Dfs(edge[B].to, y + 1); } } if (!XZ&&!y) Belong[x] = Block; } void Slove() { for (int i = 0; i<2 * M; i++) if (edge[i].ans) flag[edge[i].id / 2] = 1; for (int i = Start; i <= End; i++) { if (!TxT[i]) { TxT[i] = 1; Block++; Dfs(i, 0); } } } int main() { while (~scanf("%d%d", &N, &M)) { init(); for (int i = 0; i < M; i++) { scanf("%d%d", &U[i], &V[i]); AddEdge(U[i], V[i]); } Start = 1; End = N; Tarjan(1, -1); Slove(); for (int i = 0; i < M; i++) if (Belong[U[i]] != Belong[V[i]]) SUM[Belong[U[i]]]++, SUM[Belong[V[i]]]++; int ANS = 0; for (int i = 1; i <= Block; i++) if (SUM[i] == 1) ANS++; if (ANS % 2 == 0) printf("%d\n", ANS / 2); else printf("%d\n", ANS / 2 + 1); } return 0; }