网络流小结
@
有上下界限制网络流建图
无源汇有上下界可行流
- 设下界为B,上界为C。先让每条边流过B的流量,下界变为0,上界变为C-B。
- 这样初始流会不满足流量平衡。添加一个附加流\(g\),满足\(\sum_{(u,i)\in E}[B(u,i)+g(u,i)] = \sum_{(i,v)\in E}[B(i,v)+g(i,v)]\),\(B+g\)是实际流量\(f\)
- 令\(M(i)=\sum_{(u,i)\in E}B(u,i) - \sum_{(i,v)\in E}B(i,v) = \sum_{(i,v)\in E}g(i,v) - \sum_{(u,i)\in E}g(u,i)\) = \(i\)点的流入的下界之和减流出的下界之和
- 若\(M(i)\ge 0:\) 我们发现附加流中流出的需要比流入的多\(M(i)\)才可以达到流量平衡,那么这些流从哪来呢。建一个源点SS,建一条从SS到\(i\)的边,容量为\(M(i)\) 。
- 若\(M(i)\lt 0:\) 我们发现附加流中流入的需要比流出的多\(M(i)\)才可以达到流量平衡,那么这些流从哪来呢。建一个汇点TT,建一条从\(i\)到TT的边,容量为\(M(i)\) 。
- 存在解的条件是:SS流出的边和流入TT的边满流。
115. 无源汇有上下界可行流
const int MXN = 2e3 + 7;
const int MXE = 1e5 + 7;
int n, m;
struct DINIC{
int tot,vt,vs;
int d[MXN],head[MXN];
struct lp{
int v,w,nex;
}cw[MXE];
void add_edge(int a,int b,int c){
cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
head[a]=tot;
cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
head[b]=tot;
}
bool bfs(){
memset(d,-1,sizeof(d));
queue<int>Q;
Q.push(vt);d[vt]=0;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=cw[i].nex){
int v=cw[i].v;
if(cw[i^1].w&&d[v]==-1){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[vs]!=-1;
}
int dfs(int x,int f){
if(x==vt||f==0) return f;
int use=0,w;
for(int i=head[x];i!=-1;i=cw[i].nex){
int to=cw[i].v;
if(d[to]==d[x]-1 && cw[i].w){
w=dfs(to,min(cw[i].w,f-use));
cw[i].w-=w,cw[i^1].w+=w;
use+=w;
if(use==f) return f;
}
}
//if(!use)d[x]=-1;
return use;
}
void init(int st,int ed){
tot=-1;
for(int i = 0; i <= ed; ++i) head[i] = -1;
vs=st;vt=ed;
}
int max_flow(){
int ans=0;
while(bfs())ans+=dfs(vs,INF);
return ans;
}
}dinic;
int in[MXN], out[MXN], vs, vt, ans[MXE];
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = read();
vs = 0, vt = n + 1;
dinic.init(vs, vt);
for(int i = 0, a, b, c, d; i < m; ++i) {
a = read(), b = read(), c = read(), d = read();
dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
out[a] += c, in[b] += c;
ans[i] += c;
}
for(int i = 1; i <= n; ++i) {
if(in[i] >= out[i]) {
dinic.add_edge(vs, i, in[i] - out[i]);
}else {
dinic.add_edge(i, vt, out[i] - in[i]);
}
}
int flow = dinic.max_flow(), flag = (flow != 0);
for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[i].w != 0) flag = 0;
}
for(int i = dinic.head[vt]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[1^i].w != 0) flag = 0;
}
for(int i = 0, j = 0; j < m; ++j, i += 2) {
ans[j] += dinic.cw[i^1].w;
}
if(flag) {
printf("YES\n");
for(int i = 0; i < m; ++i) printf("%d\n", ans[i]);
}else printf("NO\n");
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
return 0;
}
116. 有源汇有上下界最大流
方法1:
加TS无穷大边,变成无源汇求可行流,判断是否有解,记录TS边流过的流量,然后删除T->S边和SS与TT所有边及点,求ST最大流,ans = TS边流过的流量+此时最大流
方法2:
加TS无穷大边,变成无源汇求可行流,判断是否有解,删点超源汇(都行),求ST最大流,ans = 最大流
(坑:卡了我的Isap!!!莫名其妙我的Isap跑一次最大流后得到的不是最大流,还得在跑一次,居然还能跑出流量来?除非用一种暴力建图我的Isap才不会出现那个问题。。。
const int MXN = 2e3 + 7;
const int MXE = 1e5 + 7;
int n, m;
struct DINIC{
int tot,vt,vs;
int d[MXN],head[MXN];
struct lp{
int v,w,nex;
}cw[MXE];
void add_edge(int a,int b,int c){
cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
head[a]=tot;
cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
head[b]=tot;
}
bool bfs(){
memset(d,-1,sizeof(d));
queue<int>Q;
Q.push(vt);d[vt]=0;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=cw[i].nex){
int v=cw[i].v;
if(cw[i^1].w&&d[v]==-1){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[vs]!=-1;
}
int dfs(int x,int f){
if(x==vt||f==0) return f;
int use=0,w;
for(int i=head[x];i!=-1;i=cw[i].nex){
int to=cw[i].v;
if(d[to]==d[x]-1 && cw[i].w){
w=dfs(to,min(cw[i].w,f-use));
cw[i].w-=w,cw[i^1].w+=w;
use+=w;
if(use==f) return f;
}
}
//if(!use)d[x]=-1;
return use;
}
void init(int st,int ed){
tot=-1;
for(int i = 0; i <= ed; ++i) head[i] = -1;
vs=st;vt=ed;
}
int max_flow(){
int ans=0;
while(bfs())ans+=dfs(vs,INF);
return ans;
}
}dinic;
int in[MXN], out[MXN], vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = read(), s = read(), t = read();
vs = 0, vt = n + 1;
dinic.init(vs, vt);
int flow = 0, flag, all = 0;
for(int i = 0, a, b, c, d; i < m; ++i) {
a = read(), b = read(), c = read(), d = read();
dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
out[a] += c, in[b] += c;
}
int tmp = dinic.tot + 1;
for(int i = 1; i <= n; ++i) {
if(in[i] > out[i]) {
dinic.add_edge(vs, i, in[i] - out[i]);
all += in[i] - out[i];
}else if(in[i] < out[i]){
dinic.add_edge(i, vt, out[i] - in[i]);
}
}
dinic.add_edge(t, s, INF);
// for(int i = 0, a, b, c, d; i < m; ++i) {
// a = read(), b = read(), c = read(), d = read();
// dinic.addEdge(a, b, d, c);
// out[a] += c, in[b] += c;
// all += c;
// }
// dinic.addEdge(t, s, INF, 0);
flow = dinic.max_flow(), flag = (flow != 0);
for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {//判断是否满流
if(dinic.cw[i].w != 0) flag = 0;
}
for(int i = dinic.head[vt]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[1^i].w != 0) flag = 0;
}
// flag = (flow == all);
if(flag) {
//法1:求可行流,删除T->S边和SS与TT所有边及点,求ST最大流,ans = 可行流+最大流
flow = dinic.cw[dinic.head[t]^1].w;
for(int i = tmp; i <= dinic.tot; ++i) {
dinic.cw[i].v = 0;
}
dinic.head[vs] = dinic.head[vt] = -1;
dinic.vs = s, dinic.vt = t;
flow += dinic.max_flow();
//法2:判断可行流,删点(都行),求ST最大流,ans = 最大流
// dinic.head[vs] = dinic.head[vt] = -1;
// dinic.vs = s, dinic.vt = t;
// flow = dinic.max_flow();
printf("%d\n", flow);
}else printf("please go home to sleep\n");
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
return 0;
}
暴力建图才能过的Isap
const int MXN = 2e3 + 7;
const int MXE = 1e5 + 7;
int n, m;
struct I_SAP{
struct lp {
int v,nex;
int cap,flow;
} cw[MXE];
int NE,NV, vs, vt;
int head[MXN],pre[MXN],cur[MXN],level[MXN],gap[MXN];
inline void add_edge(int u,int v,int cap){
cw[NE].v = v;cw[NE].cap = cap;cw[NE].flow = 0;cw[NE].nex = head[u];
head[u] = NE++;
cur[u] = head[u];
cw[NE].v = u;cw[NE].cap = 0;cw[NE].flow = 0;cw[NE].nex = head[v];
head[v] = NE++;
cur[v] = head[v];
}
inline void add_edge(int u,int v,int flow, int cap){
cw[NE].v = v;cw[NE].cap = flow;cw[NE].flow = 0;cw[NE].nex = head[u];
head[u] = NE++;
cur[u] = head[u];
}
void addEdge(int fro, int too, int val, int lim){
add_edge(fro, too, val-lim, lim);
add_edge(too, fro, 0, lim);
add_edge(vs, too, lim, lim);
add_edge(too, vs, 0, lim);
add_edge(fro, vt, lim, lim);
add_edge(vt, fro, 0, lim);
}
inline void bfs(int vt){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int>que;
que.push(vt);
while(!que.empty()) {
int u=que.front();
que.pop();
for(int i=head[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(level[v]!=-1)continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
}
int SAP(int vs,int vt){
bfs(vt);
clr(pre, -1);
for(int i = 0; i <= NV; ++i) pre[i] = -1;
//for(int i=0;i<=n;++i)cur[i]=head[i];
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV) {
bool flag=false;
for(int &i=cur[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(cw[i].cap>cw[i].flow&&level[u]==level[v]+1) {
flag=true;
pre[v]=u;
u=v;
// aug=(aug==-1?cw[i].cap:min(aug,cw[i].cap));
aug=min(aug,cw[i].cap-cw[i].flow );
if(v==vt) {
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
cw[cur[u]].flow+=aug;
cw[cur[u]^1].flow-=aug;
}
// aug=-1;
aug=INF;
}
break;
}
}
if(flag)continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(cw[i].cap>cw[i].flow&&level[v]<minlevel) {
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0)break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
}
void init(int _s, int _t, int all){
NE = 0; NV = all + 1;
vs = _s; vt = _t;
for(int i = 0; i <= NV; ++i) head[i] = cur[i] = -1;
clr(head, -1), clr(cur, -1);
}
}dinic;
int in[MXN], out[MXN], vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = read(), s = read(), t = read();
vs = 0, vt = n + 1;
dinic.init(vs, vt, vt + 1);
int flow = 0, flag, all = 0;
// for(int i = 0, a, b, c, d; i < m; ++i) {
// a = read(), b = read(), c = read(), d = read();
// dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
// out[a] += c, in[b] += c;
// all += c;
// }
// for(int i = 1; i <= n; ++i) {
// if(in[i] >= out[i]) {
// dinic.add_edge(vs, i, in[i] - out[i]);
// }else {
// dinic.add_edge(i, vt, out[i] - in[i]);
// }
// }
// dinic.add_edge(t, s, INF);
for(int i = 0, a, b, c, d; i < m; ++i) {
a = read(), b = read(), c = read(), d = read();
dinic.addEdge(a, b, d, c);
out[a] += c, in[b] += c;
all += c;
}
dinic.addEdge(t, s, INF, 0);
flow = dinic.SAP(vs, vt), flag = (flow != 0);
// debug(flow, all)
for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[i].cap != dinic.cw[i].flow) flag = 0;
}
for(int i = dinic.head[vt]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[1^i].cap != dinic.cw[1^i].flow) flag = 0;
}
flag = (flow >= all);
if(flag) {
//法1:求可行流,删除T->S边,求ST最大流,ans = 可行流+最大流
//法2:判断可行流,删点(都行),求ST最大流,ans = 最大流
dinic.head[vs] = dinic.head[vt] = -1;
flow = dinic.SAP(s, t);
printf("%d\n", flow);
}else printf("please go home to sleep\n");
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
return 0;
}
117. 有源汇有上下界最小流
做法1:
加TS无穷大边变成无源汇形式求可行流,记录TS无穷大边流量,判断是否有解,删除TS无穷大边(甚至可以把超源汇点及相邻边全删掉),然后残余网络上求TS最大流,ans=TS无穷大边流量 - TS最大流。
做法2:
建超级源汇点求出最大流,连TS无穷大的边,再跑一遍超源汇最大流,判断超级源点出去的边是否满流,TS边流过的流量即为答案。
//法1:
const int MXN = 5e5 + 7;
const int MXE = 4e5 + 7;
int n, m;
struct DINIC {
int tot, vt, vs, NV;
int d[MXN], head[MXN], cur[MXN];
struct lp {
int v, nex;
LL w;
}cw[MXE];
void add_edge(int a,int b,LL c) {
cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
head[a]=tot;
cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
head[b]=tot;
}
bool bfs() {
for(int i = 0; i <= NV + 1; ++i) d[i] = -1;
queue<int>Q;
Q.push(vt);d[vt]=0;
while(!Q.empty()) {
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=cw[i].nex) {
int v=cw[i].v;
if(cw[i^1].w&&d[v]==-1){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[vs]!=-1;
}
LL dfs(int x,LL f) {
if(x==vt||f==0) return f;
LL use=0,w;
for(int &i=cur[x];i!=-1;i=cw[i].nex) {
int to=cw[i].v;
if(d[to]==d[x]-1 && cw[i].w) {
w=dfs(to,min(cw[i].w,f-use));
cw[i].w-=w,cw[i^1].w+=w;
use+=w;
if(use==f) return f;
}
}
//if(!use)d[x]=-1;
return use;
}
void init(int st,int ed) {
tot = -1;
for(int i = 0; i <= ed + 1; ++i) head[i] = -1;
vs = st; vt = ed;
}
LL max_flow(){
LL ans = 0;
while(bfs()) {
for(int i = 0; i <= NV + 1; ++i) cur[i] = head[i];
ans+=dfs(vs,INFLL);
}
return ans;
}
}dinic;
LL in[MXN], out[MXN];
int vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = read(), s = read(), t = read();
vs = 0, vt = n + 1;
dinic.init(vs, vt);
dinic.NV = vt;
LL flow = 0, flow2 = 0, flag = 1, all = 0;
for(LL i = 0, a, b, c, d; i < m; ++i) {
a = read(), b = read(), c = read(), d = read();
dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
out[a] += c, in[b] += c;
}
int ret = dinic.tot;
for(int i = 1; i <= n; ++i) {
if(in[i] >= out[i]) {
dinic.add_edge(vs, i, in[i] - out[i]);
all += in[i] - out[i];
}else if(in[i] < out[i]){
dinic.add_edge(i, vt, out[i] - in[i]);
}
}
dinic.add_edge(t, s, INFLL);
int tmp = dinic.tot;
dinic.max_flow();
flow = dinic.cw[dinic.tot].w;
// for(int i = 0, a, b, c, d; i < m; ++i) {
// a = read(), b = read(), c = read(), d = read();
// dinic.addEdge(a, b, d, c);
// out[a] += c, in[b] += c;
// all += c;
// }
// dinic.addEdge(t, s, INF, 0);
for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[i].w) flag = false;
}
// for(int i = tmp; i >= ret + 1; --i) dinic.cw[i].w = dinic.cw[i].v = 0;
// dinic.head[vs] = -1, dinic.head[vt] = -1;
dinic.head[t] = dinic.cw[dinic.head[t]].nex;
dinic.head[s] = dinic.cw[dinic.head[s]].nex;
dinic.vs = t, dinic.vt = s;
flow2 = dinic.max_flow();
if(flag) {
printf("%lld\n", flow - flow2);
}else printf("please go home to sleep\n");
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
return 0;
}
//法2:
const int MXN = 5e5 + 7;
const int MXE = 4e5 + 7;
int n, m;
struct DINIC{
int tot, vt, vs;
int d[MXN], head[MXN], cur[MXN];
struct lp{
int v, nex;
LL w;
}cw[MXE];
void add_edge(int a,int b,LL c){
cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
head[a]=tot;
cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
head[b]=tot;
}
bool bfs(){
for(int i = 0; i <= vt + 1; ++i) d[i] = -1;
queue<int>Q;
Q.push(vt);d[vt]=0;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=cw[i].nex){
int v=cw[i].v;
if(cw[i^1].w&&d[v]==-1){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[vs]!=-1;
}
LL dfs(int x,LL f){
if(x==vt||f==0) return f;
LL use=0,w;
for(int &i=cur[x];i!=-1;i=cw[i].nex){
int to=cw[i].v;
if(d[to]==d[x]-1 && cw[i].w){
w=dfs(to,min(cw[i].w,f-use));
cw[i].w-=w,cw[i^1].w+=w;
use+=w;
if(use==f) return f;
}
}
//if(!use)d[x]=-1;
return use;
}
void init(int st,int ed){
tot=-1;
for(int i = 0; i <= ed; ++i) head[i] = -1;
vs=st;vt=ed;
}
LL max_flow(){
LL ans=0;
while(bfs()) {
for(int i = vs; i <= vt; ++i) cur[i] = head[i];
ans+=dfs(vs,INFLL);
}
return ans;
}
}dinic;
LL in[MXN], out[MXN];
int vs, vt, s, t;
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = read(), s = read(), t = read();
vs = 0, vt = n + 1;
dinic.init(vs, vt);
LL flow = 0, flow2 = 0, flag = 1, all = 0;
for(LL i = 0, a, b, c, d; i < m; ++i) {
a = read(), b = read(), c = read(), d = read();
dinic.add_edge(a, b, d - c);//减去流量下界,假做已经流过B的流量
out[a] += c, in[b] += c;
}
for(int i = 1; i <= n; ++i) {
if(in[i] > out[i]) {
dinic.add_edge(vs, i, in[i] - out[i]);
all += in[i] - out[i];
}else if(in[i] < out[i]){
dinic.add_edge(i, vt, out[i] - in[i]);
}
}
flow = dinic.max_flow();
dinic.add_edge(t, s, INFLL);
// for(int i = 0, a, b, c, d; i < m; ++i) {
// a = read(), b = read(), c = read(), d = read();
// dinic.addEdge(a, b, d, c);
// out[a] += c, in[b] += c;
// all += c;
// }
// dinic.addEdge(t, s, INF, 0);
flow2 = dinic.max_flow();
for(int i = dinic.head[vs]; ~i; i = dinic.cw[i].nex) {
if(dinic.cw[i].w) flag = false;
}
if(flag) {
assert(flow2 == dinic.cw[dinic.head[t]^1].w);
printf("%lld\n", dinic.cw[dinic.head[t]^1].w);
}else printf("please go home to sleep\n");
#ifndef ONLINE_JUDGE
cout << "time cost:" << 1.0*clock()/CLOCKS_PER_SEC << "ms" << endl;
#endif
return 0;
}
板子题:洛谷P3376
I_SAP
struct I_SAP{
struct lp {
int v,nex;
int cap,flow;
} cw[MXE];
int NE,NV, vs, vt;
int head[MXN],pre[MXN],cur[MXN],level[MXN],gap[MXN];
inline void add_edge(int u,int v,int cap){
cw[NE].v = v;cw[NE].cap = cap;cw[NE].flow = 0;cw[NE].nex = head[u];
head[u] = NE++;
cur[u] = head[u];
cw[NE].v = u;cw[NE].cap = 0;cw[NE].flow = 0;cw[NE].nex = head[v];
head[v] = NE++;
cur[v] = head[v];
}
inline void bfs(int vt){
memset(level,-1,sizeof(level));
memset(gap,0,sizeof(gap));
level[vt]=0;
gap[level[vt]]++;
queue<int>que;
que.push(vt);
while(!que.empty()) {
int u=que.front();
que.pop();
for(int i=head[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(level[v]!=-1)continue;
level[v]=level[u]+1;
gap[level[v]]++;
que.push(v);
}
}
}
int SAP(int vs,int vt){
bfs(vt);
memset(pre,-1,sizeof(pre));
//for(int i=0;i<=n;++i)cur[i]=head[i];
int u=pre[vs]=vs,flow=0,aug=INF;
gap[0]=NV;
while(level[vs]<NV) {
bool flag=false;
for(int &i=cur[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(cw[i].cap>cw[i].flow&&level[u]==level[v]+1) {
flag=true;
pre[v]=u;
u=v;
// aug=(aug==-1?cw[i].cap:min(aug,cw[i].cap));
aug=min(aug,cw[i].cap-cw[i].flow );
if(v==vt) {
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]) {
cw[cur[u]].flow+=aug;
cw[cur[u]^1].flow-=aug;
}
// aug=-1;
aug=INF;
}
break;
}
}
if(flag)continue;
int minlevel=NV;
for(int i=head[u]; i!=-1; i=cw[i].nex) {
int v=cw[i].v;
if(cw[i].cap>cw[i].flow&&level[v]<minlevel) {
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==0)break;
level[u]=minlevel+1;
gap[level[u]]++;
u=pre[u];
}
return flow;
}
void init(int _s, int _t, int all){
NE = 0; NV = all + 1;
vs = _s; vt = _t;
for(int i = 0; i <= NV; ++i) head[i] = cur[i] = -1;
}
}sap;
DINIC1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<bitset>
#define mme(a,b) memset((a),(b),sizeof((a)))
#define precision(x,d) cout<<fixed<<setprecision(d)<<x<<"\n"
#define iis std::ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int MXN = 1e4+7;
const int MXE = 4e5+7;
int vs, vt;
struct DINIC{
int tot,vt,vs;
int d[MXN],head[MXN];
struct lp{
int v,w,nex;
}cw[MXE];
void add_edge(int a,int b,int c){
cw[++tot].v=b;cw[tot].nex=head[a],cw[tot].w=c;
head[a]=tot;
cw[++tot].v=a;cw[tot].nex=head[b],cw[tot].w=0;
head[b]=tot;
}
bool bfs(){
memset(d,-1,sizeof(d));
queue<int>Q;
Q.push(vt);d[vt]=0;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=cw[i].nex){
int v=cw[i].v;
if(cw[i^1].w&&d[v]==-1){
d[v]=d[u]+1;
Q.push(v);
}
}
}
return d[vs]!=-1;
}
/*int dfs(int x,int low){
if(x==vt||low==0)return low;
int flow=0,used=0;
for(int i=head[x];i!=-1;i=cw[i].nex){
int v=cw[i].to;
if(cw[i].w&&d[v]+1==d[x]&&(used=dfs(v,min(low,cw[i].w)))>0){
//used=dfs(v,min(low,cw[i].w));
if(!used)continue;
flow+=used,low-=used;
cw[i].w-=used;cw[i^1].w+=used;
if(!low)break;
}
}
if(!flow)d[x]=-1;
return flow;
}*/
int dfs(int x,int f){
if(x==vt||f==0) return f;
int use=0,w;
for(int i=head[x];i!=-1;i=cw[i].nex){
int to=cw[i].v;
if(d[to]==d[x]-1 && cw[i].w){
w=dfs(to,min(cw[i].w,f-use));
cw[i].w-=w,cw[i^1].w+=w;
use+=w;
if(use==f) return f;
}
}
if(!use)d[x]=-1;
return use;
}
void init(int st,int ed){
tot=-1;
memset(head,-1,sizeof(head));
vs=st;vt=ed;
}
int max_flow(){
int ans=0;
while(bfs())ans+=dfs(vs,INF);
return ans;
}
}dinic;
int main(){
int u,v,w,n,m;
scanf("%d%d%d%d",&n,&m,&vs,&vt);
dinic.init(vs,vt);
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&u,&v,&w);
dinic.add_edge(u,v,w);
}
printf("%d\n",dinic.max_flow());
return 0;
}
Isap
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include <cstdio>
#include <cstring>
using namespace std;
const int inf = 0x3fffffff;
template <int N, int M>
struct Isap{
int top;
int d[N], pre[N], cur[N], gap[N];
struct Vertex {
int head;
} V[N];
struct Edge {
int v, next;
int c, f;
} E[M];
void init() {
memset(V, -1, sizeof(V));
top = 0;
}
void add_edge(int u, int v, int c) {
E[top].v = v;
E[top].c = c;
E[top].f = 0;
E[top].next = V[u].head;
V[u].head = top++;
}
void add(int u, int v, int c) {
add_edge(u, v, c);
add_edge(v, u, 0);
}
void set_d(int t) {
queue<int> Q;
memset(d, -1, sizeof(d));
memset(gap, 0, sizeof(gap));
d[t] = 0;
Q.push(t);
while (!Q.empty()) {
int v = Q.front(); Q.pop();
++gap[d[v]];
for (int i = V[v].head; ~i; i = E[i].next) {
int u = E[i].v;
if (d[u] == -1) {
d[u] = d[v] + 1;
Q.push(u);
}
}
}
}
int sap(int s, int t, int num) {
set_d(t);
int ans = 0, u = s;
int flow = inf;
memcpy(cur, V, sizeof(V));
while (d[s] < num) {
int &i = cur[u];
for (; ~i; i = E[i].next) {
int v = E[i].v;
if (E[i].c > E[i].f && d[u] == d[v] + 1) {
u = v;
pre[v] = i;
flow = min(flow, E[i].c - E[i].f);
if (u == t) {
while (u != s) {
int j = pre[u];
E[j].f += flow;
E[j ^ 1].f -= flow;
u = E[j ^ 1].v;
}
ans += flow;
flow = inf;
}
break;
}
}
if (i == -1) {
if (--gap[d[u]] == 0)
break;
int dmin = num - 1;
cur[u] = V[u].head;
for (int j = V[u].head; ~j; j = E[j].next)
if (E[j].c > E[j].f)
dmin = min(dmin, d[E[j].v]);
d[u] = dmin + 1;
++gap[d[u]];
if (u != s)
u = E[pre[u] ^ 1].v;
}
}
return ans;
}
};
Isap<200005, 400005> Sap;
int tux[100001], tuy[100001],st,zt;
int main(){
int n, m;
scanf("%d%d%d%d", &n, &m, &st, &zt);
int q, w, e;
Sap.init();
for (int a = 1; a <= m; a++){
scanf("%d%d%d", &q, &w, &e);
Sap.add(q, w, e);
}
printf("%d\n",Sap.sap(st, zt, 9 * m + 2));
return 0;
}
ACMer,无怨无悔