sgu 176 上下界网络流最小可行流带输出方案

算法步骤:

  1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流.

  2. 加上刚才没有加上的那条边p

  3. 再跑一遍超级源汇之间的最大流,p的流量就是我们要求的最小可行流流量(等于其反向边的"容量")

收获:

  1. 最大可行流和最小可行流,当我们把其残量网络求出来后,其流量就是dst->src的残量.

    每条边在此时的流量 = 流量下界 + 转换后对应边的流量

  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 }

时间: 2024-08-14 05:39:53

sgu 176 上下界网络流最小可行流带输出方案的相关文章

zoj 3229 上下界网络最大可行流带输出方案

收获: 1. 上下界网络流求最大流步骤: 1) 建出无环无汇的网络,并看是否存在可行流 2) 如果存在,那么以原来的源汇跑一次最大流 3) 流量下界加上当前网络每条边的流量就是最大可行流了. 2. 输出方案: 可以把边的位置信息一起存在边表中,求完最大流后遍历一下边,把信息更新过去. 1 #include <cstdio> 2 #include <cstring> 3 #define min(a,b) ((a)<(b)?(a):(b)) 4 #define oo 0x3f3f

hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流推断 )

题意:有n个点和m条有向边构成的网络.每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏全部S到T的路径的费用和 > 毁坏全部T到S的路径的费用和 + 重建这些T到S的双向路径的费用和. 思路1: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center&quo

hdu 4940 Destroy Transportation system( 无源汇上下界网络流的可行流判断 )

题意:有n个点和m条有向边构成的网络,每条边有两个花费: d:毁坏这条边的花费 b:重建一条双向边的花费 寻找这样两个点集,使得点集s到点集t满足 毁坏所有S到T的路径的费用和 > 毁坏所有T到S的路径的费用和 + 重建这些T到S的双向路径的费用和. 思路1: 然后这个无源汇带上下界网络流的可行流问题的求解方法见这里~~ 建图就是上面说的那样啦~最后判断有没有可行流就是求一下我们所构造的这个新的网络的最大流~然后判断一下这个最大流是否满流~(即判断最大流是否和附加源点的流出总量相等~~) cod

ZOJ2314 Reactor Cooling(无源汇流量有上下界网络的可行流)

题目大概说一个核反应堆的冷却系统有n个结点,有m条单向的管子连接它们,管子内流量有上下界的要求,问能否使液体在整个系统中循环流动. 本质上就是求一个无源汇流量有上下界的容量网络的可行流,因为无源汇的容量网络上各个顶点都满足流量平衡条件,即所有点的∑流入流量=∑流出流量,可以看成里面的流是循环流动的,类似有向图欧拉回路. 而带上下界的网络可行流的求法,是根据网络流中一个流是可行流的充分必要条件——限制条件和平衡条件,去改造原网络,转化成不带下界的容量网络来求解的.数学模型那些证明之类的不难理解,见

POJ2396 Budget(有源汇流量有上下界网络的可行流)

题目大概给一个有n×m个单元的矩阵,各单元是一个非负整数,已知其每行每列所有单元的和,还有几个约束条件描述一些单元是大于小于还是等于某个数,问矩阵可以是怎样的. 经典的流量有上下界网络流问题. 把行.列看成点,各单元看成边 源点向各行连容量下界0上界该行和的边,各列向汇点连容量下界0上界该列和的边 对于各单元,其对应行列表示的边间连下界上界和约束条件对应的边 这样就是求解这个网络的可行流,可以通过汇点向源点连容量INF的边,使各个顶点都满足平衡条件,这样转化成无源汇有上下界网络流来求解. 最后就

sgu 194 上下界网络流可行流判定+输出可行流

1 #include <cstdio> 2 #include <cstring> 3 #define min(a,b) ((a)<(b)?(a):(b)) 4 #define oo 0x3f3f3f3f 5 #define N 210 6 #define M 100010 7 8 struct Dinic { 9 int n, src, dst; 10 int head[N], dest[M], flow[M], eid[M], next[M], etot; 11 int c

sgu 194上下界网络流

又搞了个模板,这个模板应该ok,足以应付各种网络流了 题意:给n个点m 条边,其中每条边的流量有两个限制不能大于r不能小于l,求是否有可行解,如有输出每条边的流量 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn = 1000000; const int oo = 0x3777777; st

@总结 - 8@ 上下界网络流等一类网络流问题

目录 @0 - 参考资料@ @1 - 问题引入@ @2 - 上下界可行流@ @3 - 上下界最大流/最小流@ @4 - 上下界费用流@ @5 - 带负环的最小费用流@ @6 - 例题与参考代码实现@ @7 - 一些类似的杂题@ @0 - 参考资料@ menci 的博客 liu_runda 的博客 @1 - 问题引入@ 我们知道,通常情况下,一个合法的流应该具有如下几个性质: (1)(除源点汇点以外)流量守恒:\(\sum f(i, u) = \sum f(u, j)\). (2)斜对称性:\(f

[BZOJ2502]清理雪道 有上下界网络流(最小流)

2502: 清理雪道 Time Limit: 10 Sec  Memory Limit: 128 MB Description 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机,每次飞行可以从总部带一个人降落到滑雪场的某个地点,然后再飞回总部.从降落的地点出发,这个人可以顺着斜坡向下滑行,并清理他所经过的雪道. 由于每次飞行的耗费是固定的,为了最小化耗费