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 0x3f3f3f3f
  5 #define N 1500
  6 #define M 500000
  7
  8 struct Dinic {
  9     int n, src, dst;
 10     int head[N], dest[M], flow[M], next[M], info[M][2], etot;
 11     int cur[N], dep[N], qu[N], bg, ed;
 12     void init( int n, int src, int dst ) {
 13         this->n = n;
 14         this->src = src;
 15         this->dst = dst;
 16         etot = 0;
 17         memset( head, -1, sizeof(head) );
 18     }
 19     void adde( int i, int j, int u, int v, int f ) {
 20         next[etot]=head[u],flow[etot]=f,dest[etot]=v,info[etot][0]=i,info[etot][1]=j; head[u]=etot++;
 21         next[etot]=head[v],flow[etot]=0,dest[etot]=u,info[etot][0]=-1,info[etot][1]=-1; head[v]=etot++;
 22     }
 23     bool bfs() {
 24         memset( dep, 0, sizeof(dep) );
 25         qu[bg=ed=1] = src;
 26         dep[src] = 1;
 27         while( bg<=ed ) {
 28             int u=qu[bg++];
 29             for( int t=head[u]; t!=-1; t=next[t] ) {
 30                 int v=dest[t], f=flow[t];
 31                 if( f && !dep[v] ) {
 32                     dep[v] = dep[u]+1;
 33                     qu[++ed] = v;
 34                 }
 35             }
 36         }
 37         return dep[dst];
 38     }
 39     int dfs( int u, int a ) {
 40         if( u==dst || a==0 ) return a;
 41         int remain=a, past=0, na;
 42         for( int &t=cur[u]; t!=-1; t=next[t] ) {
 43             int v=dest[t], &f=flow[t], &vf=flow[t^1];
 44             if( f && dep[v]==dep[u]+1 && (na=dfs(v,min(remain,f))) ) {
 45                 f -= na;
 46                 vf += na;
 47                 remain -= na;
 48                 past += na;
 49                 if( !remain ) break;
 50             }
 51         }
 52         return past;
 53     }
 54     int maxflow() {
 55         int f=0;
 56         while( bfs() ) {
 57             memcpy( cur, head, sizeof(cur) );
 58             f += dfs(src,oo);
 59         }
 60         return f;
 61     }
 62 }D;
 63 struct Btop {
 64     int n;
 65     int head[N], dest[M], bval[M], tval[M], next[M], info[M][2], etot;
 66     int si[N], so[N];
 67     void init( int n ) {
 68         this->n = n;
 69         etot = 0;
 70         memset( head, -1, sizeof(head) );
 71         memset( si, 0, sizeof(si) );
 72         memset( so, 0, sizeof(so) );
 73     }
 74     void adde( int i, int j, int u, int v, int b, int t ) {
 75         next[etot]=head[u],tval[etot]=t,bval[etot]=b,dest[etot]=v;
 76         info[etot][0]=i, info[etot][1]=j;
 77         si[v] += b, so[u] += b;
 78         head[u]=etot++;
 79     }
 80     bool ok() {
 81         int src=n+1, dst=n+2;
 82         D.init( dst, src, dst );
 83         for( int u=1; u<=n; u++ )
 84             for( int t=head[u]; t!=-1; t=next[t] ) {
 85                 int v=dest[t];
 86                 D.adde( info[t][0], info[t][1], u, v, tval[t]-bval[t] );
 87             }
 88         int sum = 0;
 89         for( int u=1; u<=n; u++ ) {
 90             if( si[u]>so[u] ) {
 91                 D.adde( -1, -1, src, u, si[u]-so[u] );
 92                 sum += si[u]-so[u];
 93             } else if( so[u]>si[u] ) {
 94                 D.adde( -1, -1, u, dst, so[u]-si[u] );
 95             }
 96         }
 97         return sum==D.maxflow();
 98     }
 99 }B;
100
101 int n, m;
102 int c[375];
103 int ans[375][110], tot;
104
105 int main() {
106     while( scanf( "%d%d", &n, &m ) == 2 ) {
107         int src=n+m+1, dst=src+1;
108         B.init(dst);
109         for( int i=1,g; i<=m; i++ ) {
110             scanf( "%d", &g );
111             B.adde( -1, -1, n+i, dst, g, oo );
112         }
113         memset( ans, 0, sizeof(ans) );
114         tot = 0;
115         for( int i=1,d; i<=n; i++ ) {
116             scanf( "%d%d", c+i, &d );
117             B.adde( -1, -1, src, i, 0, d );
118             for( int j=1,t,l,r; j<=c[i]; j++ ) {
119                 scanf( "%d%d%d", &t, &l, &r );
120                 t++;
121                 B.adde( i, j, i, n+t, l, r );
122                 ans[i][j] = l;
123                 tot += l;
124             }
125         }
126         B.adde( -1, -1, dst, src, 0, oo );
127         bool ok = B.ok();
128         if( !ok ) {
129             printf( "-1\n" );
130         } else {
131             D.src=src;
132             D.dst=dst;
133             D.maxflow();
134             for( int t=0; t<D.etot; t++ ) {
135                 int i=D.info[t][0], j=D.info[t][1];
136                 if( ~i && ~j ) {
137                     ans[i][j] += D.flow[t^1];
138                     tot += D.flow[t^1];
139                 }
140             }
141             printf( "%d\n", tot );
142             for( int i=1; i<=n; i++ )
143                 for( int j=1; j<=c[i]; j++ )
144                     printf( "%d\n", ans[i][j] );
145         }
146         printf( "\n" );
147     }
148 }

时间: 2024-08-05 06:39:46

zoj 3229 上下界网络最大可行流带输出方案的相关文章

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

算法步骤: 1. 先将原图像最大可行流那样变换,唯一不同的是不加dst->src那条边来将它变成无源无汇的网络流图.直接跑一边超级源到超级汇的最大流. 2. 加上刚才没有加上的那条边p 3. 再跑一遍超级源汇之间的最大流,p的流量就是我们要求的最小可行流流量(等于其反向边的"容量") 收获: 1. 最大可行流和最小可行流,当我们把其残量网络求出来后,其流量就是dst->src的残量. 每条边在此时的流量 = 流量下界 + 转换后对应边的流量 1 #include <c

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

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

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

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

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

ZOJ3229 Shoot the Bullet(有源汇流量有上下界网络的最大流)

题目大概说在n天里给m个女孩拍照,每个女孩至少要拍Gi张照片,每一天最多拍Dk张相片且都有Ck个拍照目标,每一个目标拍照的张数要在[Lki, Rki]范围内,问最多能拍几张照片. 源点-天-女孩-汇点,这样子建容量网络.然后就是求这个有源汇流量有上下界容量网络的最大流: 首先计算其可行流,POJ2396 然后删除附加源.附加汇以及汇点到源点容量INF的边 最后从源点到汇点跑一边最大流即可 1 #include<cstdio> 2 #include<cstring> 3 #inclu

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

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

poj 3189 Steady Cow Assignment 【最大流】【枚举上下界 判断是否满流】

Steady Cow Assignment Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6029   Accepted: 2083 Description Farmer John's N (1 <= N <= 1000) cows each reside in one of B (1 <= B <= 20) barns which, of course, have limited capacity. So

BZOJ 2324 (有上下界的)费用流

思路: 先跑一遍Floyd  更新的时候map[i][j]=map[i][k]+map[k][j]  k需要小于i或j 正常建边: 把所有点 拆点-> i,i+n add(x,y,C,E)表示x->y建边 话费为C  容量为E add(S,0,0,k) add(i,j+n,map[i][j],1) add(j+n,j,0,0x3f3f3f3f)->这条边下界为1 add(j,T,0,1) 这个时候我们有两种方法 1.套用有上下界的网络流 2.把add(j+n,j,0,0x3f3f3f3f