sgu 176 上下界网络流最小可行流带输出方案
算法步骤:
1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流.
2. 加上刚才没有加上的那条边p
3. 再跑一遍超级源汇之间的最大流,p的流量就是我们要求的最小可行流流量(等于其反向边的"容量")
收获:
1. 最大可行流和最小可行流,当我们把其残量网络求出来后,其流量就是dst->src的残量.
每条边在此时的流量 = 流量下界 + 转换后对应边的流量
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cassert> 3 #include <cstring> 4 #define min(a,b) ((a)<(b)?(a):(b)) 5 #define oo 0x3f3f3f3f 6 #define N 110 7 #define M N*N 8 9 struct Dinic { 10 int n, src, dst; 11 int head[N], dest[M], flow[M], next[M], info[M], etot; 12 int cur[N], dep[N], qu[N], bg, ed; 13 void init( int n ) { 14 this->n = n; 15 memset( head, -1, sizeof(head) ); 16 etot = 0; 17 } 18 void adde( int i, int u, int v, int f ) { 19 info[etot]=i, flow[etot]=f, dest[etot]=v, next[etot]=head[u]; head[u]=etot++; 20 info[etot]=0, flow[etot]=0, dest[etot]=u, next[etot]=head[v]; head[v]=etot++; 21 } 22 bool bfs() { 23 memset( dep, 0, sizeof(dep) ); 24 qu[bg=ed=1] = src; 25 dep[src] = 1; 26 while( bg<=ed ) { 27 int u=qu[bg++]; 28 for( int t=head[u]; t!=-1; t=next[t] ) { 29 int v=dest[t], f=flow[t]; 30 if( f && !dep[v] ) { 31 dep[v]=dep[u]+1; 32 qu[++ed] = v; 33 } 34 } 35 } 36 return dep[dst]; 37 } 38 int dfs( int u, int a ) { 39 if( u==dst || a==0 ) return a; 40 int remain=a, past=0, na; 41 for( int &t=cur[u]; t!=-1; t=next[t] ) { 42 int v=dest[t], &f=flow[t], &vf=flow[t^1]; 43 if( f && dep[v]==dep[u]+1 && (na=dfs(v,min(remain,f))) ) { 44 f -= na; 45 vf += na; 46 remain -= na; 47 past += na; 48 if( !remain ) break; 49 } 50 } 51 return past; 52 } 53 int maxflow( int s, int t ) { 54 int f = 0; 55 src = s, dst = t; 56 while( bfs() ) { 57 memcpy( cur, head, sizeof(cur) ); 58 f += dfs(src,oo); 59 } 60 return f; 61 } 62 }dinic; 63 struct Btop { 64 int n; 65 int head[N], dest[M], bval[M], tval[M], next[M], info[M], etot; 66 int sumi[N], sumo[N]; 67 void init( int n ) { 68 etot = 0; 69 memset( head, -1, sizeof(head) ); 70 this->n = n; 71 } 72 void adde( int i, int u, int v, int b, int t ) { 73 info[etot]=i, bval[etot]=b, tval[etot]=t; 74 dest[etot]=v, next[etot]=head[u]; 75 sumi[v]+=b, sumo[u]+=b; 76 head[u] = etot++; 77 } 78 int minflow( int src, int dst ) { 79 int ss=n+1, tt=n+2, sum; 80 dinic.init( n+2 ); 81 for( int u=1; u<=n; u++ ) 82 for( int t=head[u]; t!=-1; t=next[t] ) { 83 int v=dest[t]; 84 dinic.adde( info[t], u, v, tval[t]-bval[t] ); 85 } 86 sum = 0; 87 for( int u=1; u<=n; u++ ) { 88 if( sumi[u]>sumo[u] ) { 89 dinic.adde( 0, ss, u, sumi[u]-sumo[u] ); 90 sum += sumi[u]-sumo[u]; 91 } else if( sumo[u]>sumi[u] ) { 92 dinic.adde( 0, u, tt, sumo[u]-sumi[u] ); 93 } 94 } 95 int f = 0; 96 f += dinic.maxflow(ss,tt); 97 dinic.adde( 0, dst, src, oo ); 98 f += dinic.maxflow(ss,tt); 99 if( f!=sum ) return -1; 100 int eid = dinic.etot-2; 101 return dinic.flow[eid^1]; 102 } 103 }btop; 104 105 int n, m; 106 int ans[M], tot; 107 108 int main() { 109 scanf( "%d%d", &n, &m ); 110 btop.init( n ); 111 for( int i=1,u,v,z,c; i<=m; i++ ) { 112 scanf( "%d%d%d%d", &u, &v, &z, &c ); 113 if( c==1 ) btop.adde( i, u, v, z, z ); 114 else btop.adde( i, u, v, 0, z ); 115 ans[i] = c ? z : 0; 116 } 117 int minf = btop.minflow(1,n); 118 if( minf==-1 ) { 119 printf( "Impossible\n" ); 120 return 0; 121 } 122 for( int e=0; e<dinic.etot; e++ ) { 123 int i=dinic.info[e]; 124 if( i ) ans[i] += dinic.flow[e^1]; 125 } 126 printf( "%d\n", minf ); 127 for( int i=1; i<=m; i++ ) 128 printf( "%d ", ans[i] ); 129 printf( "\n" ); 130 }