POJ 1966 最大流最小割...

来源:互联网 发布:原油理财软件 编辑:程序博客网 时间:2024/05/01 00:27

最近写的代码都挺长的啊...

下面说一下最小割吧。

以下内容引自:这里

首先介绍一个概念:

点连通度:一个具有N个顶点的图G,去除K个顶点后,图成为非连通图,去除任意K-1个顶点后,图仍为连通图。责成图G为K连通图。

独立轨:A,B是图G中两个顶点,从A至B的无公共内顶点的路径叫做独立轨,其最大条数记为p(A,B);


如上图中,将A=1,B=5;那么该图的最大独立轨数量为3

1-2-3-5,1-4-5,1-7-6-5;三条。

在这三条独立轨中,每条切除一个内点,该图的成为非连通图。如果p(G)=N-1,则该图为强连通图。

可见p(A,B)=K(G)。也就是图G独立轨的最大条数为图G的连通度。

由于每个内点只能用一次,可以套最大流模型...

将顶点v分割为v,v',e=(v,v')容量为1;做一次最大流就可以得出源点到汇点的最小割。

G无向图:

(1)顶点v分割为v,v'。e(v,v')容量为1;

(2)图中的无向边设为2条有向边,e(u,v)-->e(u',v)=INF,e(v',u)=INF;

(3)枚举源点u'和汇点v做最大流。

G有向图类似。

若结果流出的值为INF,则该图为强连通,去除N个顶点才能破坏连通性。

所有具有流量为1的弧(V,V')对应的V顶点组成一个割顶集

通过求连通度可以得到一个结论:G是K的连通图,k>=2,则任意K个顶点共圈。


边连通度:

解法类似,不过边连通,点可以走很多次,边只能走一次。

(1)对于无向边e(u,v) 在(u,v),(v,u)之间添加容量为1的流边。

(2)枚举源点汇点,求最大流,即为边连通度。

求出的残余网络中,流量为1的弧e`=(u,v),e`就是割边。





#include<iostream>#include<string>#include<cstdio>#include<cstdlib>#include<algorithm>#define MN 111#define INF 0x3FFFFFFF#define CC(a) memset( a,0,sizeof(a) )#define FF(i,N) for( int i=0;i<N;i++ )template<class T>void inline checkmin( T &a,T b ){ if( a>b||a==-1 ) a=b; }template<class T>void inline checkmax( T &a,T b ){ if( a<b ) a=b; }using namespace std;int maze[MN][MN],map[MN][MN],dis[MN],cur[MN],gap[MN],pre[MN];int N,M,s,t;void setG(){  CC(map);  FF( i,N )   map[i][i+N]=1;  int u,v;  FF( i,M ){   scanf( " (%d,%d)",&u,&v );   map[u+N][v]=map[v+N][u]=INF; }}void initG(){  FF(i,N<<1)FF(j,N<<1)  maze[i][j]=map[i][j];}int sap( int s,int t ){ CC(cur),CC(gap),CC(dis); int u=pre[s]=s,maxflow=0,aug=-1; gap[0]=2*N; while( dis[s]<2*N ){loop:    for( int v=cur[u];v<2*N;v++ )    if( maze[u][v]&&dis[u]==dis[v]+1 )   {      pre[v]=u;      cur[u]=v;      checkmin( aug,maze[u][v] );      u=v;      if( v==t )      {      maxflow+=aug;      for( u=pre[u];v!=s;v=u,u=pre[u] )      maze[u][v]-=aug,maze[v][u]+=aug;      aug=-1;         }   goto loop;   }   int mind=2*N;   for( int v=0;v<2*N;v++ )   if( maze[u][v]&&mind>dis[v] )   {      mind=dis[v];      cur[u]=v;      }      if( --gap[dis[u]]==0 ) break;      gap[dis[u]=mind+1]++;      u=pre[u];  }  return maxflow;}int main(){ while( scanf("%d%d",&N,&M)!=EOF ) {    int ans=INF;    setG();    for( int i=0;i<N;i++ )    for( int j=i+1;j<N;j++ )   {      initG();      checkmin( ans,sap(i+N,j) );      //printf( "ans:%d\n",ans );      }      if( ans==INF )         printf( "%d\n",N );      else         printf( "%d\n",ans );  } return 0;}