[BZOJ 1718] Redundant Paths
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1718
[算法]
用Tarjan算法找出所有e-DCC(边-双联通分量),然后将这张图缩点,答案即为(缩点后的树的叶子节点的个数 + 1) / 2
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 5010 #define MAXM 10010 struct edge { int to,nxt; } e[MAXM << 1]; int i,n,m,cnt,s,timer,tot; int head[MAXN],u[MAXM],v[MAXM],low[MAXN],dfn[MAXN],belong[MAXN],degree[MAXN]; bool is_bridge[MAXM << 1]; inline void addedge(int u,int v) { tot++; e[tot] = (edge){v,head[u]}; head[u] = tot; } inline void tarjan(int u,int t) { int i,v; dfn[u] = low[u] = ++timer; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (!dfn[v]) { tarjan(v,i); low[u] = min(low[u],low[v]); if (low[v] > dfn[u]) is_bridge[i] = is_bridge[i ^ 1] = true; } else if (i != (t ^ 1)) low[u] = min(low[u],dfn[v]); } } inline void dfs(int u) { int i,v; belong[u] = cnt; for (i = head[u]; i; i = e[i].nxt) { v = e[i].to; if (!belong[v] && !is_bridge[i]) dfs(v); } } int main() { scanf("%d%d",&n,&m); tot = 1; for (i = 1; i <= m; i++) { scanf("%d%d",&u[i],&v[i]); addedge(u[i],v[i]); addedge(v[i],u[i]); } for (i = 1; i <= n; i++) { if (!dfn[i]) tarjan(i,0); } for (i = 1; i <= n; i++) { if (!belong[i]) { cnt++; dfs(i); } } for (i = 1; i <= m; i++) { if (belong[u[i]] != belong[v[i]]) { degree[belong[u[i]]]++; degree[belong[v[i]]]++; } } for (i = 1; i <= cnt; i++) s += (degree[i] == 1); printf("%d\n",(s + 1) / 2); return 0; }