网络流模板-网络单纯形

最小费用最大流,但能过 HLPP 板子题,还能处理负环

无上下界
namespace flow{ // }{{{
constexpr int VV = 1200, EE = 120000;
constexpr int V = VV+1, E = EE;
struct Edge{ int to; ll lf, cost; int nxt; } es[E*2+4];
int head[V], fa[V], fe[V], tim, mark[V], ecnt;
ll pi[V];
ll minc, maxf, sumflow, sumcost;
void init(){
    minc = maxf = sumflow = sumcost = 0;
    tim = ecnt = 2;
    std::fill(head, head+V, 0);
    std::fill(fe, fe+V, 0);
    std::fill(mark, mark+V, 0);
}
void addflow(int s, int t, ll f, ll c){
    s++, t++;
    es[ecnt] = {t, f, c, head[s]}, head[s] = ecnt++;
    es[ecnt] = {s, 0, -c, head[t]}, head[t] = ecnt++;
    sumflow += f; sumcost += std::abs(c);
}
void mktree(int x, int fre){
    fe[x] = fre;
    fa[x] = es[fre^1].to;
    mark[x] = 1;
    for(int i=head[x]; i; i=es[i].nxt){
        if(es[i].lf == 0 || mark[es[i].to] == 1) continue;
        mktree(es[i].to, i);
    }
}
ll getpi(int x){
    if(mark[x] == tim) return pi[x];
    mark[x] = tim;
    return pi[x] = getpi(fa[x]) + es[fe[x]].cost;
}
ll pushflow(int e){
    int rt = es[e].to, lca = es[e^1].to;
    ++tim;
    while(rt){ mark[rt] = tim; rt = fa[rt]; }
    while(mark[lca] != tim){ mark[lca] = tim; lca = fa[lca]; }
    static std::vector<int> topush;
    int dir = -1, todel = e; ll df = es[e].lf;
    topush.clear();
    topush.push_back(e);
    UP(j, 0, 2) for(int i=es[e^!j].to; i!=lca; i=fa[i]){
        if(es[fe[i]^j].lf < df){
            df = es[fe[i]^j].lf;
            todel = fe[i]^j;
            dir = j;
        }
        topush.push_back(fe[i]^j);
    }
    ll dcst = 0;
    if(df) for(int i:topush){
        es[i].lf -= df;
        es[i^1].lf += df;
        dcst += es[i].cost * df;
    }
    if(todel == e) return dcst;
    int laste = e^!dir;
    for(int i=es[e^!dir].to; i!=es[todel^!dir].to; ){
        int ii = fa[i];
        std::swap(laste, fe[i]);
        laste ^= 1;
        fa[i] = es[fe[i]^1].to;
        mark[i] = 0;
        i = ii;
    }
    return dcst;
}
void mcmf(int is, int it){
    ll sfl = sumflow+1, scs = sumcost+1; 
    addflow(it, is, sfl, -scs);
    is++, it++;
    mktree(it, 0);
    int i=2,j=2;
    do{
        if(es[i].lf && es[i].cost+getpi(es[i^1].to)-getpi(es[i].to)<0){
            minc += pushflow(j=i);
        }
        i=(i==ecnt-1?2:i+1);
    } while(i!=j);
    maxf = es[ecnt-1].lf;
    minc += maxf * scs;
}
} // {}}}
有上下界
namespace flow{ // }{{{
using ll = long long;
constexpr int VV = -0x383494, EE = -0x383494;
constexpr int V = 1+VV+1, E = EE+VV+1;
struct Edge{ int to; ll lf, cost; int nxt; } es[E*2+4];
int head[V], cnt;
ll sumcost = 0, sumflow = 0, minc, maxf, pi[V], ex[V];
int is, it, iv, time, fa[V], fe[V], mark[V];
void init(int v, int s, int t){
	is = s+1, it = t+1, iv = v+2;
	sd fill(head, head+iv, 0); sd fill(mark, mark+iv, 0); sd fill(fe, fe+iv, 0); sd fill(ex, ex+iv, 0);
	time = cnt = 2;
	sumcost = sumflow = minc = maxf = 0;
}
void addflow(int s, int t, ll f, ll c, ll minf=0, bool inside = false){
	if(!inside) s++, t++;
	es[cnt] = (Edge){t, f-minf, c, head[s]}, head[s] = cnt++;
	es[cnt] = (Edge){s, 0, -c, head[t]}, head[t] = cnt++;
	ex[s] -= minf, ex[t] += minf;
	sumflow += f, sumcost += sd abs(c);
	minc += minf * c;
}
void mktree(int x, int from_e){
	fe[x] = from_e;
	fa[x] = es[from_e^1].to;
	mark[x] = 1;
	for(int i=head[x]; i; i=es[i].nxt){
		if(mark[es[i].to] == 1 || es[i].lf == 0) continue;
		mktree(es[i].to, i);
	}
}
ll getpi(int x){
	if(mark[x] == time) return pi[x];
	mark[x] = time;
	return pi[x] = getpi(fa[x]) - es[fe[x]].cost;
}
ll pushflow(int e){
	static std::vector<int> topush;
	topush.clear();
	int rt = es[e].to, lca = es[e^1].to;
	time++;
	while(rt){ mark[rt] = time; rt = fa[rt]; }
	while(mark[lca] != time){ mark[lca] = time; lca = fa[lca]; }
	ll df = es[e].lf;
   	int todel = e, dir = -1;
	UP(j, 0, 2) for(int i=es[e^!j].to; i!=lca; i=fa[i]){
		if(es[fe[i]^j].lf < df){
			df = es[fe[i]^j].lf;
			todel = fe[i];
			dir = !j;
		}
		topush.push_back(fe[i]^j);
	}
	topush.push_back(e);
	ll dcst = 0;
	if(df) for(int i:topush){
		es[i].lf -= df;
		es[i^1].lf += df;
		dcst += es[i].cost * df;
	}
	if(todel == e) return dcst;
	int last = e^dir, lastu = es[e^!dir].to;
	for(int i=es[last].to; i!=es[todel^1].to; ){
		mark[i]=time-1;
		int i_ = fa[i];
		fa[i] = lastu;
		lastu = i;
		sd swap(fe[i], last); last ^= 1;
		i=i_;
	}
	return dcst;
}
bool mcmf(){
	ll sfl_ = sumflow+1, scs_ = sumcost+1;
	int cnt_ = cnt;
	UP(i, 0, iv-1){
	   	if(ex[i] > 0){
			addflow(iv-1, i, ex[i], -scs_, 0, true);
			minc += scs_*ex[i];
		} else if(ex[i] < 0){
			addflow(i, iv-1, -ex[i], 0, 0, true);
		}
	}
#if !(NO_FROM_TO)
	addflow(it, is, sfl_, -scs_, 0, true);
#endif
	sumflow = sfl_-1, sumcost = scs_-1;
	mktree(iv-1, 0);
	mark[iv-1] = ++time;
	fa[iv-1] = 0;
	for(int i=2, j=cnt-1; ; i=(i==cnt-1?2:i+1)){
		if(es[i].lf && es[i].cost+getpi(es[i].to)-getpi(es[i^1].to)<0){
			minc += pushflow(j=i);
		} else if(i==j) break;
	}
	UP(i, cnt_, cnt-2){
		if(es[i].lf != 0) return false;
		i++;
	}
	maxf = es[cnt-1].lf;
#if !(NO_FROM_TO)
	minc += maxf * scs_;
#endif
	return true;
}
} // {}}}
posted @ 2023-06-16 20:27  383494  阅读(54)  评论(0编辑  收藏  举报