求无向图的点连通度。
解决办法:拆点,转换为求边连通度。
通常情况下怎么求边连通度?给每条边赋权值1,任意选择源点,枚举汇点,依次求最小割。
那么求无向图的点连通度该怎么建图?
拆点,对于原始无向图中的边(a,b),在新图中有(a+N,b)=(b+N,a)=INF。同时对i<N有(i,i+N)=1。
任意选择起点,枚举汇点,求(start+N,end)的最大流,即最小割。
需要注意的是,当最小割的值大于等于N,即边连通度为N。
#include <algorithm> #include <iostream> using namespace std; #define MAXN 105 #define INF 105 #define MIN(x,y) (x<y?x:y) int map[MAXN][MAXN]; 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; }