/********************************************************************
** @brief 图的连通度问题是指:在图中删去部分元素(点或边),使得图中指定的两个点s和t不连通
(不存在从s到t的路径),求至少要删去几个元素。
图的连通度分为点连通度和边连通度:
(1)点连通度:只许删点,求至少要删掉几个点(当然,s和t不能删去,这里保证原图中至少有三个点);
(2)边连通度:只许删边,求至少要删掉几条边。
并且,有向图和无向图的连通度求法不同,因此还要分开考虑(对于混合图,只需将其中所有的无向边按照
无向图的办法处理、有向边按照有向图的办法处理即可)。
【1】有向图的边连通度:
这个其实就是最小割问题。以s为源点,t为汇点建立网络,原图中的每条边在网络中仍存在,容量为1,
求该网络的最小割(也就是最大流)的值即为原图的边连通度。
【2】有向图的点连通度:
需要拆点。建立一个网络,原图中的每个点i在网络中拆成i'与i'',有一条边<i', i''>,容量为1
(<s', s''>和<t', t''>例外,容量为正无穷)。原图中的每条边<i, j>在网络中为边<i'', j'>,
容量为正无穷。以s'为源点、t''为汇点求最大流,最大流的值即为原图的点连通度。
说明:最大流对应的是最小割。显然,容量为正无穷的边不可能通过最小割,也就是原图中的边和s、t两个点
不能删去;若边<i, i''>通过最小割,则表示将原图中的点i删去。
【3】无向图的边连通度:
将图中的每条边(i, j)拆成<i, j>和<j, i>两条边,再按照有向图的办法(【1】)处理;
【4】无向图的点连通度:
将图中的每条边(i, j)拆成<i, j>和<j, i>两条边,再按照有向图的办法(【2】)处理。
********************************************************************/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define MAX 105
#define INF 105
int map[MAX][MAX];
int N,M;
#define MAXN 105
//#define INF 105
#define MIN(x,y) (x<y?x:y)
int n,m;
int max_flow(int num,int s,int t){//参考算法导论的 Edmonds-Karp 算法。
int f[MAX],//记录结点的父节点
min_flow[MAX];//当前路径中最小的一段的值,也即限制值
int flow[MAX][MAX];//记录当前网络中的流
queue<int>q;
int ans=0;
memset(flow,0,sizeof(flow));
while(true){//一直循环,直到不存在增广路径
while(!q.empty())q.pop();
memset(f,-1,sizeof(f));
f[s]=-2;//源点的父节点需特殊标示
min_flow[s]=INF;
q.push(s);
while(!q.empty()){//BFS寻找增广路径
int tmp=q.front();q.pop();
for(int i=0;i<num;++i){
if(f[i]==-1 && flow[tmp][i]<map[tmp][i]){//当结点i还未被探索到,并且还有可用流量
q.push(i);
f[i]=tmp;
min_flow[i]=min(min_flow[tmp],(map[tmp][i]-flow[tmp][i]));
}
}
if(f[t]!=-1){//t的父节点不为初始值,说明BFS已经找到了一条路径
int k=t;
while(f[k]>=0){
flow[f[k]][k]+=min_flow[t];//将新的流量加入flow
flow[k][f[k]]=-flow[f[k]][k];
k=f[k];
}
break;
}
}
if(f[t]==-1)return ans;//不存在增广路径,返回
else ans+=min_flow[t];
}
}
int main(int argc, char *argv[])
{
while(scanf("%d%d",&n,&m)!=EOF){
int a,b,ans;
memset(map,0,sizeof(map));
for(int i=0;i<n;++i){
map[i][i+n]=1;
}
for(int j=0;j<m;++j){
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(ans,max_flow(n*2,n,i));
}
if(ans==INF)ans=n;
printf("%d/n",ans);
}
return 0;
}
poj 1966 无向图的点连通度
最新推荐文章于 2021-08-13 12:35:50 发布