顾名思义。点连通度即使在一个图中,去掉多少个点可以使这个图不连通。
因为点连通度的求法是构图时转化为边连通度来求的。
而边连通度的求法:
构造一个流网络,每个无向边的容量为1。
任意取一个点作为源点。
枚举剩下的店作为汇点,求最小割。
枚举完取最小割最小的值就是ans。
(我的理解其实就是整体的边连通度是取决于“最短板”,即存在的两个点间连通强度最弱。)
(而刚好最小割其实就是流网络流求最大流时的“最短板”,故此时边连通度突然和最小割连通起来也不是那么不可思议了吧)
构图:(拆点)
(1) 原 G 图中的每个顶点 v 变成 N 网中的两个顶点 v' 和 v" ,顶点 v' 至 v" 有一条弧(有向边)连接,弧容量为 1;
(2) 原 G 图中的每条边 e = uv ,在 N 网中有两条弧 e’= u"v',e"=v"u' 与之对应, e' 弧容量为 ∞ , e" 弧容量为 ∞ 。
(3)A” 为源顶点, B' 为汇顶点
解法:
任意取一个点作为源点,枚举其他汇点(注意,比如取v1''作为源点,则其他汇点不包括v1')。
然后最大流最小割,取最小的最小割。
当fmin>=n(因为有可能fmin==无穷大),则ans=n。
关于点连通度和变连通度的具体定义和系统解法可以参照下面链接:
http://blog.csdn.net/bobten2008/article/details/4945141
AC代码:244K16MS
#include<iostream>
using namespace std;
#define MIN(a,b) (a<b?a:b)
const int inf=(1<<29);
const int N=105;
int n,m;
int mat[N][N];
int matinitial[N][N];
int visit[N];
int que[N];
int level[N];
bool bfs(int final)
{
memset(level,0,sizeof(level));
memset(visit,0,sizeof(visit));
int head=1,tail=1;
visit[n]=true;
level[n]=0;
que[tail++]=n;
while(head<tail)
{
int now=que[head++];
if(now==final)
{
return true;
}
for(int i=0;i<2*n;i++)
{
if(!visit[i]&&mat[now][i])
{
visit[i]=true;
que[tail++]=i;
level[i]=level[now]+1;
}
}
}
return false;
}
int dinic(int final,int now,int sum)
{
if(now==final)
{
return sum;
}
int os=sum;
for(int i=0;i<2*n&∑i++)
{
if(level[i]==level[now]+1&&mat[now][i])
{
int tmp=dinic(final,i,MIN(mat[now][i],sum));
mat[now][i]-=tmp;
mat[i][now]+=tmp;
sum-=tmp;
}
}
return os-sum;
}
void solve()
{
int fmin=inf;
int ans=0;
for(int i=1;i<n;i++)
{
ans=0;
for(int i=0;i<2*n;i++)
for(int j=0;j<2*n;j++)
{
mat[i][j]=matinitial[i][j];//每次都要重新刷新一个图网络的各种参数
}
while(bfs(i))
{
ans+=dinic(i,n,inf);
}
if(ans<fmin)
fmin=ans;
}
if(fmin>=n)
printf("%d\n",n);
else
printf("%d\n",fmin);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(matinitial,0,sizeof(matinitial));
int from,to;
for(int i=0;i<n;i++)
{
matinitial[i][i+n]=1;
}
for(int i=1;i<=m;i++)
{
scanf(" (%d,%d)",&from,&to);
matinitial[from+n][to]=inf;
matinitial[to+n][from]=inf;
}
solve();
}
return 0;
}