sgu176 Flow Construction【有源汇有上下界最小流】

  同样是模板题。

  首先将有源汇转换为无源汇,假设原来的源汇为st,我们加入的源汇为ST,那么我们应该从t到s连一条流量为+∞的边,使原来的st满足收支平衡,退化为普通节点。

  分离必要边和其他边,从S到T跑最大流,所有与源或者汇相连的边都流满则证明有解。

  去掉t到s容量为+∞的边,去掉必要边,从t到s跑最大流。

  把得到的答案相减即可。

  如果我们得到的答案是负的,那么说明它内部t到s连成了环,那么我们加上S到s容量为-ans的边,跑S到t的最大流,这样所有的边的流量应该就是0,再加上流量下界即为答案。

 1 #include <bits/stdc++.h>
 2 #define rep(i, a, b) for (int i = a; i <= b; i++)
 3 #define drep(i, a, b) for (int i = a; i >= b; i--)
 4 #define REP(i, a, b) for (int i = a; i < b; i++)
 5 #define mp make_pair
 6 #define pb push_back
 7 #define clr(x) memset(x, 0, sizeof(x))
 8 #define xx first
 9 #define yy second
10 using namespace std;
11 typedef long long i64;
12 typedef pair<int, int> pii;
13 const int inf = ~0U >> 1;
14 const i64 INF = ~0ULL >> 1;
15 //******************************
16
17 const int maxn = 105, maxm = 10105;
18
19 struct Ed {
20     int u, v, nx, c; Ed() {}
21     Ed(int _u, int _v, int _nx, int _c) :
22         u(_u), v(_v), nx(_nx), c(_c) {}
23 } E[maxm << 1];
24 int G[maxn], edtot = 1;
25 void addedge(int u, int v, int c) {
26     E[++edtot] = Ed(u, v, G[u], c);
27     G[u] = edtot;
28     E[++edtot] = Ed(v, u, G[v], 0);
29     G[v] = edtot;
30 }
31
32 int level[maxn], S, T;
33 bool bfs(int s, int t) {
34     static int que[maxn]; int qh(0), qt(0);
35     clr(level); level[que[++qt] = s] = 1;
36     while (qh != qt) {
37         int x = que[++qh]; if (qh == maxn - 1) qh = 0;
38         for (int i = G[x]; i; i = E[i].nx) if (E[i].c && !level[E[i].v]) {
39             level[que[++qt] = E[i].v] = level[x] + 1;
40             if (qt == maxn - 1) qt = 0;
41         }
42     }
43     return !!level[t];
44 }
45 int dfs(int u, int rm, int t) {
46     if (u == t) return rm;
47     int rm1 = rm;
48     for (int i = G[u]; i; i = E[i].nx) {
49         if (E[i].c && level[E[i].v] == level[u] + 1) {
50             int flow = dfs(E[i].v, min(E[i].c, rm), t);
51             E[i].c -= flow, E[i ^ 1].c += flow;
52             if ((rm -= flow) == 0) break;
53         }
54     }
55     if (rm1 == rm) level[u] = 0;
56     return rm1 - rm;
57 }
58
59 int l[maxm], in[maxn];
60 int main() {
61     int n, m;
62     scanf("%d%d", &n, &m);
63     rep(i, 1, m) {
64         int x, y, a, b; scanf("%d%d%d%d", &x, &y, &a, &b);
65         l[i] = a * b;
66         if (b) in[y] += a, in[x] -= a;
67         addedge(x, y, a - a * b);
68     }
69     S = n + 1, T = n + 2;
70     int sum(0);
71     rep(i, 1, n) {
72         if (in[i] > 0) sum += in[i];
73         if (in[i] > 0) addedge(S, i, in[i]);
74         else addedge(i, T, -in[i]);
75     }
76     addedge(n, 1, 0x3f3f3f3f);
77     while (bfs(S, T)) sum -= dfs(S, 0x3f3f3f3f, T);
78     if (sum) { puts("Impossible"); return 0; }
79     int ans = E[edtot].c;
80     E[edtot].c = E[edtot ^ 1].c = 0;
81     int tmp(0);
82     while (bfs(n, 1)) tmp += dfs(n, 0x3f3f3f3f, 1);
83     ans -= tmp;
84     if (ans < 0) {
85         addedge(S, 1, -ans);
86         while (bfs(S, n)) dfs(S, 0x3f3f3f3f, n);
87         ans = 0;
88     }
89     printf("%d\n", ans);
90     rep(i, 1, m) {
91         printf(i == 1 ? "%d" : " %d", E[(i << 1) ^ 1].c + l[i]);
92     }
93     puts("");
94     return 0;
95 }

时间: 2024-07-30 10:05:19

sgu176 Flow Construction【有源汇有上下界最小流】的相关文章

loj #117. 有源汇有上下界最小流

题目链接 有源汇有上下界最小流,->上下界网络流 注意细节,边数组也要算上后加到SS,TT边. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 7 using namespace std; 8 9 const int N = 150010; 10 const int INF = 1e9;

Flow construction SGU - 176 有源汇有上下界最小流 二分法和回流法

/** 题目:Flow construction SGU - 176 链接:https://vjudge.net/problem/SGU-176 题意: 有源汇有上下界的最小流. 给定n个点,m个管道.每个管道给出u,v,z,c.u表示起点,v表示终点,z表示容量,如果c==1,那么表示还有下界为z. 如果c==0,表示没有下界. 求从1到n的最小流. 思路: 第一种做法: 转化为无源汇求超级源S到超级汇T的最大流flow1(此时从s出发的流和为flow1),然后讲t到s的边删掉(可以使流量等于

sgu 176 Flow construction(有源汇的上下界最小流)

[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足流量平衡的最小流量. [思路] 按照可行流构造网络.不连t->s的边先跑一遍附加源汇点的最大流,然后连t->s一条inf边,在残量网络上跑一遍最大流.第一次求最大流所以能走的边都已经流满,第二次求附加源汇点最大流t->s的流量就会尽可能小. 另外还可以二分下界mid,然后连边(T,S,mid

有源汇带上下界最小流

LOj 模板 思路我就不多说了吧,和有源汇带上下界最大流一样,只不过这次是初流-残流网络最大流.关键这个模板题写的过程无限T一组,让我很绝望.在网上搜罗了很多代码,发现我有些地方可以优化. (1)跑dinic的时候可以使用当前弧优化 (2)在dinic过程中,如果rest已经等于0了,直接返回.不要不管他,感觉没什么影响,其实有的数据会卡死的(千万在边权更新之后再返回). #include<iostream> #include<cstdio> #include<cstring

#117. 有源汇有上下界最小流

题目描述 n nn 个点,m mm 条边,每条边 e ee 有一个流量下界 lower(e) \text{lower}(e)lower(e) 和流量上界 upper(e) \text{upper}(e)upper(e),给定源点 s ss 与汇点 t tt,求源点到汇点的最小流. 输入格式 第一行两个正整数 n nn.m mm.s ss.t tt. 之后的 m mm 行,每行四个整数 s ss.t tt.lower \text{lower}lower.upper \text{upper}uppe

有源汇有上下界最小流 (ZQU 1592)

这道题跟求最大流的时候差不多. 都是先构造可行流,然后判断是否可行, 可行的话,就利用残余流量,构造从汇点t跑到源点s的最大流, 如何求出答案呢. 在第一次求可行流的dinic后,跟求最大流的时候一样,从t到s是可行流的流量: 这个时候t到s的反向边,也就是s到t的流量就是t到s流的量(因为t到s定义权值为inf,要从这条边算出来,得用inf去减到这条边剩下的才是答案,有点麻烦) 所以反向边是个便捷的求法. 所以在第一次dinic之后,t到s的反向便的流量就是可行流的流量: 然后我们再从t到s跑

有上下界的网络流3-有源汇带上下界最小流SGU176

题目大意:有一个类似于工业加工生产的机器,起点为1终点为n,中间生产环节有货物加工数量限制,输入u v z c, 当c等于1时表示这个加工的环节必须对纽带上的货物全部加工(即上下界都为z),c等于0表示加工上界限制为z,下界为0,求节点1(起点)最少需要投放多少货物才能传送带正常工作. 解题思路:    1.直接 增设超级源点ss和超级汇点tt并连上附加边,对 当前图 求 无源汇带上下界可行流    2.将图的汇点sd连一条容量无限制的边到图的源点st,再求一遍 无源汇带上下界可行流    3.

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

#pragma warning(disable:4996) #include <iostream> #include <cstring> #include <string> #include <vector> #include <cstdio> #include <algorithm> #include <cmath> #include <queue> #include <map> #include

HDU 3157 Crazy Circuits(有源汇上下界最小流)

HDU 3157 Crazy Circuits 题目链接 题意:一个电路板,上面有N个接线柱(标号1~N),还有两个电源接线柱 + -,给出一些线路,每个线路有一个下限值求一个可以让所有部件正常工作的总电流 没有则输出impossible 思路: 有源汇有上下界求最小流,建模方法为: 按无源汇先建图,跑超级源汇ss->tt一次,然后加入t->s,容量INF的边,在跑一次ss->tt,如果是满流,就有解,解为t->s边的当前流量 顺带写个最大流的,最大流就先把t->s加入直接跑