大意:任意的一个图,计算让图不连通所需删去的最小点数。
分析:最近在搞网络流,所以就往那个方面想,首先,拆点。原先节点所形成的那一段的容量为1,原先点与点之间的路径的容量为无穷大。让后枚举源汇点,计算所以这些情况所取得的最大流的最小值。一开始RE许久,后来改了一下,去掉了一维,只枚举汇点,因为若图被分割成多部分时,无论以图中哪一个点为源头,一定会存在一个最大流为0的汇点。(似乎, 还可以用最小割解释,本人若菜。。。)。
#include<stdio.h>
#include<string.h>
#define eps 1e8
#define LMT 54000
typedef struct
{
int u,v,c,next;
}line;
line e[LMT],ef[LMT];
int lev[155],q[155],link[155],next[155];
int n,m,all,pal;
void insert(int u,int v,int c)
{
e[all].u=u;
e[all].v=v;
e[all].c=c;
e[all].next=next[u];
next[u]=all++;
e[all].u=v;
e[all].v=u;
e[all].next=next[v];
e[all].c=0;
next[v]=all++;
}
void copy()
{
int i;
for(i=0;i<all;i++)
ef[i]=e[i];
}
int bfs(int s,int t)
{
int head,tail,u,v,x;
head=tail=0;
memset(lev,0,sizeof(lev));
q[tail++]=s;lev[s]=1;
while(head<tail)
{
u=q[head++];
for(x=next[u];x!=-1;x=ef[x].next)
{
v=ef[x].v;
if(lev[v]==0&&ef[x].c>0)
{
lev[v]=lev[u]+1;
q[tail++]=v;
}
}
}
return lev[t];
}
int dfs(int s,int t)
{
int u,top=0,ret=0,i,x;
q[top++]=s;
while(top>0)
{
u=q[top-1];
if(u==t)
{
int back,tiny=-1;
for(i=top-1;i>0;i--)
{
x=link[q[i]];
if(tiny==-1||ef[x].c<tiny)
{
back=i;
tiny=ef[x].c;
}
}
for(i=top-1;i>0;i--)
{
x=link[q[i]];
ef[x].c-=tiny;
ef[x^1].c+=tiny;
}
top=back;
ret+=tiny;
ret=ret>eps?eps:ret;
}
else
{
for(x=next[u];x!=-1;x=ef[x].next)
if(ef[x].c>0&&lev[u]+1==lev[ef[x].v])
{
q[top++]=ef[x].v;
link[ef[x].v]=x;
break;
}
if(x==-1)
{
top--;
lev[u]=0;
}
}
}
return ret;
}
int dinic(int s,int t)
{
int ret=0;
while(bfs(s,t))
ret+=dfs(s,t);
if(ret>eps)ret=eps;
return ret;
}
int main()
{
int i,u,v,min,ret,j;
while(scanf("%d%d",&n,&m)!=EOF)
{
getchar();
if(n==1)printf("1\n");
else if(n==0||m==0)printf("0\n");
else
{
memset(next,-1,sizeof(next));
all=0;
for(i=0;i<n;i++)
insert(i,i+n,1);
while(m--)
{
scanf(" (%d,%d)",&u,&v);
insert(u+n,v,eps);
insert(v+n,u,eps);
}
min=eps;
pal=all;
for(i=1;i<n;i++)
{
copy();
ret=dinic(n,i);
if(min>ret)min=ret;
}
if(min>=eps)min=n;
printf("%d\n",min);
}
}
return 0;
}