例题:loj117 : https://loj.ac/problem/117
//其实就是判断可行流后倒着求一遍最大流
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 200010, INF = 0x7fffffff;
int d[maxn], head[maxn], in[maxn], cur[maxn];
int n, m, s, t;
int cnt = 0;
struct node{
int u, v, c, next, bz;
}Node[2*maxn];
inline void add_(int u, int v, int c, int bz)
{
Node[cnt].u = u;
Node[cnt].v = v;
Node[cnt].c = c;
Node[cnt].next = head[u];
Node[cnt].bz = bz;
head[u] = cnt++;
}
inline void add(int u, int v, int c, int bz)
{
add_(u,v,c,bz);
add_(v,u,0,bz);
}
inline bool bfs() //此处为bool类型 其它类型会TL
{
queue<int> Q;
mem(d,0);
Q.push(s);
d[s] = 1;
while(!Q.empty())
{
int u = Q.front(); Q.pop();
for(int i=head[u]; i!=-1; i=Node[i].next)
{
node e = Node[i];
if(!d[e.v] && e.c > 0)
{
d[e.v] = d[e.u] + 1;
Q.push(e.v);
if(e.v == t) return 1;
}
}
}
return d[t] != 0;
}
inline int dfs(int u, int cap)
{
int ret = 0, V;
if( u == t || cap == 0)
return cap;
for(int &i=cur[u]; i!=-1; i=Node[i].next) //千万不要忘记加引用符号
{
node e = Node[i];
if(d[e.v] == d[e.u] + 1 && e.c > 0)
{
int V = dfs(e.v, min(cap, e.c));
Node[i].c -= V;
Node[i^1].c += V;
ret += V;
cap -= V;
if(cap == 0) break;
}
}
if(cap > 0) d[u] = -1;
return ret;
}
inline int Dinic(int u)
{
int ans = 0;
while(bfs())
{
memcpy(cur,head,sizeof(head));
ans += dfs(u, INF);
}
return ans;
}
int main()
{
mem(head,-1);
int s_, t_;
scanf("%d%d%d%d",&n,&m,&s_,&t_);
s = 0; t = n+1;
int sum = 0;
for(int i=0; i<m; i++)
{
int u, v, b, d;
scanf("%d%d%d%d",&u,&v,&b,&d);
add(u, v, d-b,1);
in[v] += b;
in[u] -= b;
}
for(int i=1; i<=n; i++)
{
if(in[i] > 0)
{
sum += in[i];
add(s,i,in[i],0);
}
else
{
add(i,t,-in[i],0);
}
}
add(t_,s_,INF,0);
if(sum != Dinic(s))
{
printf("please go home to sleep
");
}
else
{
sum = Node[head[t_]^1].c;
for(int i=0; i<cnt; i++)
{
if(!Node[i].bz) Node[i].v = 0;
}
head[s] = head[t] = -1;
s = t_;
t = s_;
printf("%d
",sum - Dinic(s)); //sum 减去 反向最大流 = 正向最小流
}
return 0;
}