题目传送门

无源汇有上下界可行流问题。

设$in_i$表示至少流到i的流量,$out_i$表示至少从i流出的流量。

对于每一条从u到v,流量上界为r,下界为l的边,容量存r-l,然后$in_v = in_v + l$,$out_u = out_u + l$。

建超级源点s,超级汇点t,对于每个满足$in_i > out_i$的i,从s向i连容量为$in_i-out_i$的边,对于每个满足$out_i>in_i$的i,从i向t连容量为$out_i-in_i$的边,

接着从s向t跑最大流。

如果流量$\not=$从s连出来的边容量总和,则不行。

否则:每条边的流量为流量下界+新图中该边的流量。

/*
Author: CNYALI_LK
LANG: C++
PROG: sgu194.cpp
*/
#include<bits/stdc++.h>
#define up(a,b,c) for (int a(b),end##a(c);a<=end##a;++a)
#define down(a,c,b) for (int a(b),end##a(c);a>=end##a;--a)
#define uup(a,c,b) for (int a(b),end##a(c);a<=end##a;++a)
#define udown(a,b,c) for (int a(b),end##a(c);a>=end##a;--a)
#define endl '\n'
#define debug(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
const double eps=1e-8;
const double PI=acos(-1.0);
typedef long long ll;
struct inout{
//io优化省略
};
inout io;
template<class T>void chkmin(T &a,T b){a=a<b?a:b;}
template<class T>void chkmax(T &a,T b){a=a>b?a:b;}
int to[53333],lst[53333],w[53333],beg[233],e,s,t;
#define rev(x) (((x-1)^1)+1)
int out[233],in[233],sf[53333];
void add(int u,int v,int wea){
    to[++e]=v;
    lst[e]=beg[u];
    w[e]=wea;
    beg[u]=e;
}
int dis[233],q[233],cur[233],n;
int bfs(){
    up(i,1,n)dis[i]=0,cur[i]=beg[i];
    dis[s]=1;
    int l,r,u,v;
    l=r=1;
    q[l]=s;
    while(l<=r){
        u=q[l];
        for(int i=beg[u];i;i=lst[i])if(!dis[to[i]]&&w[i]){
            dis[to[i]]=dis[u]+1;
            q[++r]=to[i];
        }
        ++l;
    }
    return dis[t];
}
int dfs(int x,int flw){
    int f,i;
    if(x==t){
        return flw;
    }
    for(;cur[x];cur[x]=lst[cur[x]]){
        i=cur[x];
        if(w[i]&&dis[to[i]]==dis[x]+1){
            if(f=dfs(to[i],min(flw,w[i]))){
                w[i]-=f;
                w[rev(i)]+=f;
                return f;
            }
        }
    }
    return 0;
}
int main(){
#ifdef cnyali_lk
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    io.init();
    int m,u,v,ww,l,r;
    io>>n>>m;
    s=n+1;
    t=n+2;
    up(i,1,m){
        io>>u>>v>>l>>r;
        out[u]+=l;
        in[v]+=l;
        ww=r-l;
        add(u,v,ww);
        add(v,u,0);
        sf[i]=l;
    }
    int tot=0;
    up(i,1,n)if(in[i]>out[i]){add(n+1,i,in[i]-out[i]);add(i,n+1,0);tot+=in[i]-out[i];}else if(in[i]<out[i]){add(i,n+2,out[i]-in[i]);add(n+2,i,0);}
    n+=2;
    int f,sum=0;
    while(bfs()){
        while(f=dfs(s,0x3f3f3f3f)){sum+=f;}
    }
    if(sum!=tot)io<<"NO\n";
    else{
        io<<"YES\n";
        up(i,1,m){
            io<<w[i*2]+sf[i]<<endl; 
        }   
    }
    io.out();
    return 0;
}

标签: 网络流

添加新评论