题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=1789
题目大意:在一个无向图中,删除某一个点所形成的最大连通分量数目是多少。
我们知道,删除一个点某个图的连通分量增加,那么这个点是割点。
我们用cutNum[u]保存u这个点所关联的连通分量的数目。其中的最大值加上原图中
的连通分量的数目就是答案。
注意边数如果是0的话,要特判一下,此时去掉某一点连通分量数是n-1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define Maxn 10005
#define Maxm 500005
int dfn[Maxn];
int low[Maxn];
int dfs_clock;
int scc_cnt;
int root;
int n;
int total = 0;
int first[Maxn];
int next[Maxm];
struct Edge
{
int a,b;
}edge[Maxm];
int cutNum[Maxn];
void addEdge(int a,int b)
{
edge[total].a =a ,edge[total].b = b;
next[total] = first[a];
first[a] = total++;
}
void init()
{
total = 0;
memset(first,-1,sizeof(first));
}
void tarjan(int u)
{
dfn[u] = low[u] = ++dfs_clock;
int cnt = 0;
for(int i=first[u];i!=-1;i=next[i])
{
int v = edge[i].b;
if(!dfn[v])
{
tarjan(v);
cnt++;
low[u] = min(low[u],low[v]);
if( (u == root && cnt>1) || (u!=root && dfn[u]<=low[v]) )
{
cutNum[u]++;
}
}
else
{
low[u] = min(low[u],dfn[v]);
}
}
}
int cutPoint(int n)
{
int sum = 0;
dfs_clock = 0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(cutNum,0,sizeof(cutNum));
//如果是非连通图,就得用for循环了
//如果是连通图,root=1,tarjan(1)即可
for(int i=1;i<=n;i++)
{
if(!dfn[i]) sum++,root = i,tarjan(i);
}
int ans = 0;
for(int i=1;i<=n;i++)
{
ans = max(cutNum[i],ans);
}
return ans+sum;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int p,c;
int a,b;
while(scanf(" %d %d",&p,&c)!=EOF)
{
if(p == 0 && c == 0) break;
if(c == 0)
{
printf("%d\n",p-1 );
continue;
}
init();
for(int i=0;i<c;i++)
{
scanf(" %d %d",&a,&b);
a++,b++;
addEdge(a,b);
addEdge(b,a);
}
int ans = cutPoint(p);
printf("%d\n",ans);
}
return 0;
}