POJ 1966 无向图点联通度 最小割

题意:

给定一个无向图,求最少去掉多少个点后使得原图不连通(即存在两点不连通)。

题解:

暴力枚举起点终点,做最小割~取最小的即可

特判一些极端情况,比如m=0等等~

连通度总结(复习用~,转自 : http://blog.csdn.net/zhuyingqingfen/article/details/6386268 ):

图的连通度问题是指:在图中删去部分元素(点或边),使得图中指定的两个点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】)处理。

View Code
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <algorithm>
  6 
  7 #define N 500
  8 #define M 50000
  9 #define INF 1e9
 10 
 11 using namespace std;
 12 //必须暴力枚举起点和终点,因为 固定的起点可能就是割点 
 13 int head[N],to[M],next[M],len[M];
 14 int q[M*4],layer[N];
 15 bool map[N][N];
 16 int n,m,S,T,cnt,sn;
 17 
 18 inline void add(int u,int v,int w)
 19 {
 20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
 21     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
 22 }
 23 
 24 inline void read()
 25 {
 26     memset(map,0,sizeof map);
 27     sn=n<<1;
 28     int a,b;
 29     while(m--)
 30     {
 31         scanf(" (%d,%d)",&a,&b);
 32         a++,b++;
 33         map[a][b]=map[b][a]=true;
 34     }
 35 }
 36 
 37 inline void build()
 38 {
 39     memset(head,-1,sizeof head); cnt=0;
 40     for(int i=1;i<=n;i++)
 41         for(int j=1;j<=n;j++)
 42             if(map[i][j]) add(i,j+n,INF);
 43     for(int i=1;i<=n;i++)
 44     {
 45         if(i==S||i==T) add(i,i+n,INF),add(i+n,i,INF);
 46         else add(i,i+n,1),add(i+n,i,1);
 47     }
 48 }
 49 
 50 inline bool bfs()
 51 {
 52     memset(layer,-1,sizeof layer);
 53     int h=1,t=2,sta;
 54     q[1]=S; layer[S]=0;
 55     while(h<t)
 56     {
 57         sta=q[h++];
 58         for(int i=head[sta];~i;i=next[i])
 59             if(len[i]&&layer[to[i]]<0)
 60             {
 61                 layer[to[i]]=layer[sta]+1;
 62                 q[t++]=to[i];
 63             }
 64     }
 65     return layer[T]!=-1;
 66 }
 67 
 68 inline int find(int u,int cur_flow)
 69 {
 70     if(u==T) return cur_flow;
 71     int res=0,tmp;
 72     for(int i=head[u];~i&&res<cur_flow;i=next[i])
 73         if(len[i]&&layer[to[i]]==layer[u]+1)
 74         {
 75             tmp=find(to[i],min(cur_flow-res,len[i]));
 76             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
 77         }
 78     if(!res) layer[u]=-1;
 79     return res;
 80 }
 81 
 82 inline void go()
 83 {
 84     if(n<=1) {printf("%d\n",n); return;}
 85     int ans=n;
 86     for(S=1;S<=n;S++)
 87         for(T=S+1;T<=n;T++)
 88             if(map[S][T]==0)
 89             {
 90                 build();
 91                 T+=n;
 92                 int tmp=0;
 93                 while(bfs()) tmp+=find(S,INF);
 94                 ans=min(tmp,ans);
 95             }
 96     printf("%d\n",ans);
 97 }
 98 
 99 int main()
100 {
101     while(scanf("%d%d",&n,&m)!=EOF) read(),go();
102     return 0;
103 } 
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2848490.html