http://poj.org/problem?id=2117
求移除一个点以及与它相邻边后,剩下的图中最大的联通子图的数量是多少。
跑一遍tarjin统计下拆除某个点剩下的子图数量即可。注意给出的图不一定时联通的,所以要加上(sum-1)。
1 #include<iostream> 2 #include<cstdio> 3 #include<vector> 4 #include<cstring> 5 using namespace std; 6 #define LL long long 7 #define pb push_back 8 const int maxn=10010; 9 vector<int>g[maxn]; 10 int dfn[maxn],low[maxn],sub[maxn],root,sum; 11 bool vis[maxn]; 12 void dfs(int u){ 13 vis[u]=1; 14 dfn[u]=low[u]=sum++; 15 int son=0; 16 for(int i=0;i<g[u].size();++i){ 17 int v=g[u][i]; 18 if(vis[v]){ 19 low[u]=min(low[u],dfn[v]); 20 } 21 else{ 22 dfs(v); 23 if(u==root)son++; 24 else{ 25 if(low[v]>=dfn[u])sub[u]++; 26 } 27 low[u]=min(low[u],low[v]); 28 } 29 } 30 if(u==root)sub[u]=son; 31 else{ 32 sub[u]++; 33 } 34 } 35 int main(){ 36 int n,m,i,u,v; 37 while(scanf("%d%d",&n,&m)==2&&(n||m)){ 38 for(i=0;i<n;++i){ 39 g[i].clear(); 40 sub[i]=vis[i]=0; 41 }sum=0; 42 while(m--){ 43 scanf("%d%d",&u,&v); 44 g[u].pb(v); 45 g[v].pb(u); 46 } 47 int p=0,ans=0; 48 for(i=0;i<n;++i){ 49 if(!vis[i]){ 50 p++; 51 root=i; 52 dfs(i); 53 } 54 } 55 for(i=0;i<n;++i){ 56 ans=max(ans,sub[i]+p-1); 57 } 58 cout<<ans<<endl; 59 } 60 return 0; 61 }