2017青岛赛区网络赛 Smallest Minimum Cut 求最小割的最小割边数

先最大流跑一遍

在残存网络上把满流边容量+1

非满流边容量设为无穷大

在进行一次最大流即可

(这里的边都不包括建图时用于反悔的反向边)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<queue>
  5 #include<iostream>
  6 #define rep(i,a,b) for(int i=a;i<=b;++i)
  7 using namespace std;
  8 const int MAXN=210;
  9 int tmp,m,n,S,T,Ans;
 10 int tot=0,ans=0,Maxflow=0;
 11 int h[MAXN];
 12 int pointer[MAXN];
 13 int a[MAXN],path[MAXN];
 14 const int INF=~0U>>1;
 15 struct Edge{
 16     int next,to;
 17     int cap,op;                 //op指向反向边 cap为容量 f为流量
 18     int f;
 19     Edge() {};
 20     Edge(int b,int c,int nxt,int num,int flow) {to=b,cap=c,next=nxt,op=num^1,f=flow;}
 21 }edge[MAXN*10];
 22 void addedge(int a,int b,int c)  //a到b容量为c
 23 {
 24     edge[tot]=Edge(b,c,pointer[a],tot,0);
 25     pointer[a]=tot++;
 26     edge[tot]=Edge(a,0,pointer[b],tot,0);                     //建立b到a的反向边
 27     pointer[b]=tot++;
 28 }
 29 void Input()
 30 {
 31     memset(pointer,-1,sizeof(pointer));
 32     Maxflow=0,tot=0;
 33     scanf("%d%d",&n,&m);
 34     scanf("%d%d",&S,&T);
 35     int u,v,w;
 36     rep(i,1,m)
 37     {
 38         scanf("%d%d%d",&u,&v,&w);
 39         addedge(u,v,w);
 40     }
 41 }
 42 bool Dinic_restruct()          //bfs建立层次图
 43 {
 44     queue <int>q;
 45     memset(h,-1,sizeof(h));
 46     h[S]=0;q.push(S);
 47     while(!q.empty())
 48     {
 49         int u=q.front();q.pop();
 50         for(int i=pointer[u];i!=-1;i=edge[i].next)
 51         {
 52             int v=edge[i].to;
 53             if(h[v]==-1&&edge[i].cap-edge[i].f)
 54             {
 55                 h[v]=h[u]+1;
 56                 q.push(v);
 57              //   printf("v=%d T=%d u=%d
",v,T,u);
 58                 if(v==T) return true;
 59             }
 60         }
 61     }
 62     return false;
 63 }
 64 void Dinic_augment()     //dfs找最短增光路
 65 {
 66     int i,j,f,Stop=1;
 67     a[Stop]=S;
 68     while(Stop)
 69     {
 70         i=a[Stop];
 71      //   printf("augment i=%d
",i);
 72         if(i!=T)       //没到T就走一步,dfs
 73         {
 74             int v;
 75             for(j=pointer[i];j!=-1;j=edge[j].next)
 76                 {
 77                     v=edge[j].to;
 78                     if(h[v]==h[i]+1&&edge[j].cap-edge[j].f) break;
 79                 }
 80             if(j!=-1)
 81             {
 82                 a[++Stop]=v;
 83                 path[Stop]=j;
 84             }
 85             else            //回退
 86             {
 87 
 88                 Stop--;
 89                 h[i]=-1;
 90                // printf("-1 augment i=%d
",i);
 91             }
 92         }
 93         else    //找到了一条完整的路径
 94         {
 95             f=INF;
 96             for(i=Stop;i>=2;i--)
 97             {
 98                 int &t=path[i];
 99                 if(edge[t].cap-edge[t].f<f)
100                     f=edge[t].cap-edge[t].f;
101             }
102             Maxflow+=f;
103             for(int i=Stop;i>=2;i--)
104             {
105                 int &t=path[i];
106                 edge[t].f+=f;
107                 edge[t^1].f-=f;    //反向边
108                 if(edge[t].cap-edge[t].f==0) Stop=i-1;
109             }
110         }
111     }
112 }
113 void Dinic()
114 {
115     while(Dinic_restruct())
116         Dinic_augment();
117 
118 }
119 int main()
120 {
121  //   freopen("in.txt","r",stdin);
122     int T;
123     scanf("%d",&T);
124     rep(t1,1,T)
125     {
126         Input();
127         Dinic();
128        // printf("ok? Maxflow=%d
",Maxflow);
129         for(int i=0;i<tot;i+=2)
130         {
131            // printf("i=%d to=%d  w=%d
",i,edge[i].to,edge[i].cap-edge[i].f);
132             if((edge[i].cap-edge[i].f)==0)
133             {
134                 edge[i].cap+=1;
135             }
136             else
137             {
138                 edge[i].cap=INF;
139             }
140         }
141         Maxflow=0;
142         Dinic();
143         printf("%d
",Maxflow);
144     }
145     return 0;
146 }
原文地址:https://www.cnblogs.com/zhixingr/p/7618068.html