我学会了正确的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();
}
posted @ 2019-06-11 13:52  sigongzi  阅读(324)  评论(0编辑  收藏  举报