2017青岛赛区网络赛 Smallest Minimum Cut 求最小割的最小割边数
Posted 缄默火
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",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\n",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\n",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\n",Maxflow); 129 for(int i=0;i<tot;i+=2) 130 { 131 // printf("i=%d to=%d w=%d\n",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\n",Maxflow); 144 } 145 return 0; 146 }
以上是关于2017青岛赛区网络赛 Smallest Minimum Cut 求最小割的最小割边数的主要内容,如果未能解决你的问题,请参考以下文章
2017 ACM-ICPC 亚洲区(青岛赛区)网络赛 1003
2017 ACM-ICPC 亚洲区(青岛赛区)网络赛 1010
HDU 5884 Sort -2016 ICPC 青岛赛区网络赛
HDU 5879 Cure -2016 ICPC 青岛赛区网络赛