我学会了正确的dinic
以前写Isap的时候,总是被卡,然后学了一发Isap的当前弧优化,好像可以水过很多题
但是一直没明白为啥Isap会走一个环???
然后写dinic了,听说不容易被卡(来自去年九省联考的指导)
然而……我写了一遍上下界最小流,T了。。
后来发现我还是不懂为啥要当前弧,因为不会有环
于是去询问群友……
说是会重复访问流满的边
那么为了防止这一点,记录一个边表的指针,流到了立马返回流量,这样流第二次过来的时候,就会从最近的一条没流满的边开始流了
然后扔个板子。。
感觉自己水平不行。。。
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define ba 47
//#define ivorysi
#define MAXN 50010
#define MAXM 200005
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
res = 0;T f = 1;char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 +c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int to,next,cap;
}E[MAXM * 2];
int N,M,S,T,s,t;
int head[MAXN],last[MAXN],sumE = 1,deg[MAXN],Sflow,low[MAXM],cur[MAXN];
int dis[MAXN];
void add(int u,int v,int c) {
E[++sumE].to = v;
E[sumE].next = head[u];
E[sumE].cap = c;
head[u] = sumE;
}
void addtwo(int u,int v,int c) {
add(u,v,c);add(v,u,0);
}
queue<int> Q;
bool BFS() {
memset(dis,0,sizeof(dis));
while(!Q.empty()) Q.pop();
Q.push(S);dis[S] = 1;
while(!Q.empty()) {
int u = Q.front();Q.pop();
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(E[i].cap > 0) {
if(!dis[v]) {
dis[v] = dis[u] + 1;
if(v == T) return true;
Q.push(v);
}
}
}
}
return dis[T] != 0;
}
int dfs(int u,int aug) {
if(u == T) return aug;
for(int &i = cur[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(E[i].cap > 0) {
if(dis[v] == dis[u] + 1) {
int t = dfs(v,min(E[i].cap,aug));
if(t) {
E[i].cap -= t;
E[i ^ 1].cap += t;
return t;
}
}
}
}
return 0;
}
int Dinic() {
int res = 0;
while(BFS()) {
memcpy(cur,head,sizeof(head));
while(int d = dfs(S,1e9)) {
res += d;
}
}
return res;
}
void Solve() {
read(N);read(M);read(s);read(t);
S = N + 1;T = S + 1;
int a,b,u,l;
for(int i = 1 ; i <= M ; ++i) {
read(a);read(b);read(l);read(u);
addtwo(a,b,u - l);
low[i] = l;
deg[a] -= l;
deg[b] += l;
}
for(int i = 1 ; i <= N ; ++i) {
if(deg[i] > 0) {addtwo(S,i,deg[i]);Sflow += deg[i];}
else addtwo(i,T,-deg[i]);
}
Sflow -= Dinic();
addtwo(t,s,1e9);
Sflow -= Dinic();
if(Sflow != 0) puts("please go home to sleep");
else {out(E[sumE].cap);enter;}
}
int main(){
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
}