POJ 2117 (去掉一個割點的求最多連通分支)
阿新 • • 發佈:2019-01-03
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn=10000+10; int n,m; vector<int> G[maxn]; int cut[maxn]; int low[maxn]; int pre[maxn]; int dfs_clock; int tarjan(int u,int fa) { int lowu= pre[u]=++dfs_clock; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!pre[v]) { int lowv=tarjan(v,u); lowu=min(lowv,lowu); if(lowv>=pre[u]) cut[u]++; } else if(pre[v]<pre[u] && v!=fa) lowu = min(lowu,pre[v]); } return low[u]=lowu; } int main() { while(scanf("%d%d",&n,&m)==2&&n) { dfs_clock=0; memset(cut,0,sizeof(cut)); memset(pre,0,sizeof(pre)); for(int i=0;i<n;i++) G[i].clear(); for(int i=0;i<m;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } int sum=0;//計數連通分量數目 int max_cut=-10000; for(int i=0;i<n;i++)if(!pre[i]) { sum++; tarjan(i,-1); cut[i]--;//這個割點去掉能分成幾個連通分支, } for(int i=0;i<n;i++) max_cut=max(max_cut,cut[i]); printf("%d\n",sum+max_cut); } return 0; }
以下圖為例,0號點可以分成另個{1,2,3,4}和{5,6,7,8}。