求无向图的点连通度。
解决办法:拆点,转换为求边连通度。
通常情况下怎么求边连通度?给每条边赋权值1,任意选择源点,枚举汇点,依次求最小割。
那么求无向图的点连通度该怎么建图?
拆点,对于原始无向图中的边(a,b),在新图中有(a+N,b)=(b+N,a)=INF。同时对i<N有(i,i+N)=1。
任意选择起点,枚举汇点,求(start+N,end)的最大流,即最小割。
需要注意的是,当最小割的值大于等于N,即边连通度为N。
int max_flow(int num,int map[][MAXN],int source,int sink)//参数含义:结点数量 网络 源点 汇点
{
int my_queue[MAXN],queue_first,queue_end;//数组做队列 实现BFS搜索路径
int pre[MAXN],min_flow[MAXN];//记录结点的父节点 当前路径中最小的一段的值,也即限制值
int flow[MAXN][MAXN];//记录当前网络中的流
int ans=0;//最终结果
memset(flow,0,sizeof(flow));
while(1)//一直循环,直到不存在增广路径
{
queue_first=0;//初始化队列
queue_end=0;
my_queue[queue_end++]=source;
memset(pre,-1,sizeof(pre));
min_flow[source]=INF;
pre[source]=-2;//源点的父节点需特殊标示
while(queue_first<queue_end)//BFS寻找增广路径
{
int temp=my_queue[queue_first++];//出队列
for(int i=0;i<num;i++)//由结点temp往外扩展
{
if(pre[i]==-1&&flow[temp][i]<map[temp][i])//当结点i还未被探索到,并且还有可用流量
{
my_queue[queue_end++]=i;//加入队列
pre[i]=temp;//标示父节点
min_flow[i]=MIN(min_flow[temp],(map[temp][i]-flow[temp][i]));//求得min_flow
}
}
if(pre[sink]!=-1)//sink的父节点不为初始值,说明BFS已经找到了一条路径
{
int k=sink;
while(pre[k]>=0)
{
flow[pre[k]][k]+=min_flow[sink];//将新的流量加入flow
flow[k][pre[k]]=-flow[pre[k]][k];
k=pre[k];
}
break;
}
}
if(pre[sink]==-1) return ans;//不存在增广路径,返回
else ans+=min_flow[sink];
}
}
int N,M;
int main()
{
while(EOF!=scanf("%d%d",&N,&M))
{
int a,b,ans;
memset(map,0,sizeof(map));
for(int i=0;i<N;i++) map[i][i+N]=1;
for(int i=0;i<M;i++)
{
scanf(" (%d,%d)",&a,&b);
map[b+N][a]=map[a+N][b]=INF;
}
ans=INF;
for(int i=1;i<N;i++)
{
ans=min(max_flow(N*2,map,0+N,i),ans);
}
if(ans==INF) ans=N;
printf("%d/n",ans);
}
return 0;
}