2017青島賽區網絡賽 Smallest Minimum Cut 求最小割的最小割邊數
阿新 • • 發佈:2017-10-02
ext size 完整 bool minimum nbsp 網絡賽 else include
先最大流跑一遍
在殘存網絡上把滿流邊容量+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,intc,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 求最小割的最小割邊數