有源汇有上下界最大流 模板

//有源汇有上下界最大流
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2005,maxm=100005;
const int inf=0x7f7f7f7f;
struct edge{
    int to,next,w,num;
}lst[maxm];int len=0,first[maxn],_first[maxn];
void addedge(int a,int b,int w,int num){
    lst[len].num=num;
    lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++;
    lst[len].num=num;
    lst[len].to=a;lst[len].next=first[b];lst[len].w=0;first[b]=len++;
}
int q[maxn],vis[maxn],dis[maxn],T,s,t,head,tail,ss,tt;
bool bfs(){
    head=tail=0;vis[s]=++T;q[tail++]=s;
    while(head!=tail){
        int x=q[head++];
        for(int pt=first[x];pt!=-1;pt=lst[pt].next){
            if(lst[pt].w&&vis[lst[pt].to]!=T){
                vis[lst[pt].to]=T;dis[lst[pt].to]=dis[x]+1;q[tail++]=lst[pt].to;
            }
        }
    }
    if(vis[t]==T)memcpy(_first,first,sizeof(first));
    return vis[t]==T;
}
int dfs(int x,int lim){
    if(x==t)return lim;
    int flow=0,a;
    for(int pt=_first[x];pt!=-1;pt=lst[pt].next){
        _first[x]=pt;
        if(lst[pt].w&&dis[lst[pt].to]==dis[x]+1&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))){
            lst[pt].w-=a;lst[pt^1].w+=a;flow+=a;
            if(flow==lim)return flow;
        }
    }
    return flow;
}
int dinic(){
    int ans=0,x;
    while(bfs())
        while(x=dfs(s,inf))ans+=x;
    return ans;
}
int totflow[maxn];
void Add(int a,int b,int lo,int hi,int num){
    totflow[a]-=lo;totflow[b]+=lo;
    addedge(a,b,hi-lo,num);
}
int low[maxm],ans[maxm];
int n,m,tot;
void bound_flow(){
    int sum=0;
    for(int i=s;i<=t;++i){
        if(totflow[i]<0){
            addedge(i,tt,-totflow[i],0);
        }else{
            sum+=totflow[i];
            addedge(ss,i,totflow[i],0);
        }
    }
    addedge(t,s,0x7f7f7f7f,0);
    int tmps=s,tmpt=t;
    s=ss;t=tt;
    if(dinic()==sum){
        for(int pt=first[ss];pt!=-1;pt=lst[pt].next){
            lst[pt].w=lst[pt^1].w=0;
        }
        for(int pt=first[tt];pt!=-1;pt=lst[pt].next){
            lst[pt].w=lst[pt^1].w=0;
        }
        int flow0=lst[len-1].w;
        lst[len-1].w=lst[len-2].w=0;
        s=tmps;t=tmpt;
        printf("%d\n",flow0+dinic());
        for(int i=1;i<=m;++i){
            for(int pt=first[i+n];pt!=-1;pt=lst[pt].next){
                if(lst[pt].num!=0){
                    ans[lst[pt].num]=lst[pt].w+low[lst[pt].num];
                }
            }
        }
        for(int i=1;i<=tot;++i)printf("%d\n",ans[i]);
    }else{
        printf("-1\n");
    }
}

void work(){
    s=0;t=n+m+1;
    ss=n+m+2;tt=n+m+3;
    memset(first,-1,sizeof(first));len=0;
    memset(totflow,0,sizeof(totflow));
    int x,y;
    for(int i=1;i<=m;++i){
        scanf("%d",&x);
        Add(n+i,t,x,inf,0);
    }
    int l,h;
    tot=0;
    for(int i=1;i<=n;++i){
        scanf("%d%d",&x,&y);
        Add(s,i,0,y,0);
        for(int j=1;j<=x;++j){
            ++tot;
            scanf("%d%d%d",&y,&l,&h);
            Add(i,n+y+1,l,h,tot);low[tot]=l;
        }
    }
    bound_flow();printf("\n");
}
int main(){
    while(scanf("%d%d",&n,&m)!=EOF)work();
    return 0;
}


另一个写法

//这个好像快一点

#include <bits/stdc++.h>
using namespace std;
const int N = 210, M = 100010, INF = 1000000010;
int n, m, s, t, ss, tt, cnt = 1;
int head[N], in[N], fifo[N], depth[N];
struct edge {
    int v, nxt, w;
} vec[M];
void addedge(int u, int v, int w) {
    vec[++cnt] = (edge){ v, head[u], w };
    head[u] = cnt;
}
void add(int u, int v, int w) {
    addedge(u, v, w);
    addedge(v, u, 0);
}
void get_read() {
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for (int i = 1; i <= m; ++i) {
        int u,v,l,r;
        scanf("%d%d%d%d",&u,&v,&l,&r);
        in[u] -= l, in[v] += l;
        add(u, v, r - l);
    }
}
bool bfs(int s, int t) {
    memset(depth, 0, sizeof(depth));
    int f = 0, r = 1;
    fifo[1] = s;
    depth[s] = 1;
    while (f < r) {
        int u = fifo[++f];
        for (int i = head[u]; i; i = vec[i].nxt) {
            int v = vec[i].v;
            if (!depth[v] && vec[i].w > 0) {
                depth[v] = depth[u] + 1;
                fifo[++r] = v;
            }
        }
    }
    return depth[t];
}
int dfs(int u, int exp, int t) {
    if (!exp || u == t)return exp;
    int flow = 0;
    for (int i = head[u]; i; i = vec[i].nxt) {
        int v = vec[i].v;
        if (depth[v] == depth[u] + 1 && vec[i].w > 0) {
            int tmp = dfs(v, min(vec[i].w, exp), t);
            exp -= tmp, flow += tmp;
            vec[i].w -= tmp, vec[i ^ 1].w += tmp;
            if (!exp)
                break;
        }
    }
    if (!flow) depth[u] = -1;
    return flow;
}
int dicnic(int s, int t) {
    int ret = 0;
    while (bfs(s, t)) ret += dfs(s, INF, t);
    return ret;
}
void get_work() {
    ss = n + 1;
    tt = n + 2;
    for (int i = 1; i <= n; ++i) {
        if (in[i] > 0)
            add(ss, i, in[i]);
        else
            add(i, tt, -in[i]);
    }
    add(t, s, INF);
    int ret = 0;
    dicnic(ss, tt);
    for (int i = head[ss]; i; i = vec[i].nxt) {
        if (vec[i].w) {
            printf("please go home to sleep");
            exit(0);
        }
    }
    head[s] = vec[head[s]].nxt;
    head[t] = vec[head[t]].nxt;
    printf("%d", vec[cnt].w + dicnic(s, t));
}

int main() {
    get_read();
    get_work();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值