【题目描述】:
停电,漆黑的夜晚。
ACM + +是一家电力公司。该公司拥有数个发电厂,每一个供应一个小面积,这些发电厂给这个公司带来了很多的麻烦,在某些地区没有足够的电力,而在其他地区却有大量的盈余。
ACM ++因此决定将一些发电厂连接成一个网络。当然第一阶段,没有必要将所有的发电厂连接到一个网络,但另一方面,它必须在关键地方建立冗余连接,即网络不保证是连通的。现在提出了各种连接的计划,并已开始复杂的评估。
必须考虑的评估标准之一是创建的网络的可靠性。我们假设可以发生的最坏的事件是一个发电厂故障,这可能会导致网络分成几个部分。虽然每一部分都可以工作,但被分成的部分越多,麻烦可能性就越大。因此,我们必须找出所有方案中,某个电厂故障,会形成的最大块数。
【输入描述】:
输入由若干实例组成。
每个实例第一行都包含两个整数P和C(1 <= P = 10,000,C >= 0),中间用空格隔开。P是电厂的数量。电厂编号为0到P - 1之间的整数。C是边数。下面的C行,每一行包含两个整数0 < = P1,P2<P用一个空格隔开,这意味着电厂P1和P2连接。每个连接不会重复描述。输入终止的行包含两个零。
【输出描述】:
输出由若干行组成。输出的第i行对应于第i个输入实例。输出的每一行由一个整数组成,即通过在实例中删除一个连接点,最多可以使网络分成的最大块数。
【样例输入】:
3 3
0 1
0 2
2 1
4 2
0 1
2 3
3 1
1 0
0 0
【样例输出】:
1
2
2
【时间限制、数据范围及描述】:
时间:1s 空间:64M
1 <= P = 10,000
注意没有边的情况
【解题思路】:
算法:Tarjan算法应用–无向图 ,即Tarjan算法求割点、桥、缩点
【AC代码】:
#include<bits/stdc++.h>
#define M(a,b) memset(a,b,sizeof(a))
#define pi 3.1415926
using namespace std;
int n,m,t,tip,i;
int p[100005],dfn[100005],low[100005],cut[100005];
struct node{
int next;
int u,v;
}edge[100005*2];
void insert(int u,int v){
edge[++tip].u=u;
edge[tip].v=v;
edge[tip].next=p[u];
p[u]=tip;
}
inline void read(int &x){
char ch=getchar(),c=ch;
x=0;
while(ch<'0' || ch>'9'){
c=ch;
ch=getchar();
}
while(ch>='0' && ch<='9'){
x=(x<<1)+(x<<3)+ch-'0';
ch=getchar();
}
if(c=='-')x=-x;
}
void tarjan(int u,int fa){
dfn[u]=low[u]=++t;
for(int i=p[u];i;i=edge[i].next){
int v=edge[i].v;
if(v==fa)continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u])cut[u]++;
}
else low[u]=min(low[u],dfn[v]);
}
return ;
}
int main(){
int a,b;
while(1){
int c=0;
int ans=-1;
tip=t=0;
M(edge,0);
M(p,0);
M(dfn,0);
M(low,0);
M(cut,0);
read(n),read(m);
if(m==0&&n==0)break;
for(i=0;i<m;i++){
read(a),read(b);
insert(a+1,b+1);
insert(b+1,a+1);
}
for(i=1;i<=n;i++){
if(dfn[i]==0){
c++;
cut[i]=-1;
tarjan(i,-1);
}
}
for(i=1;i<=n;i++)ans=max(ans,cut[i]);
printf("%d\n",ans+c);
}
return 0;
}