zoj2314 无源汇上下界可行流

题意:看是否有无源汇上下界可行流,如果有输出流量

题解:对于每一条边u->v,上界high,下界low,来说,我们可以建立每条边流量为high-low,那么这样得到的流量可能会不守恒(流入量!=流出量),这时我们要想使得流量守恒,我们需要建立附加流,附加流 是在刚才的图上的改进流,对于每一个点如果有流入量(in)>流出量(out),那么对于多余的流入量,我们需要想办法新加一条边流量为in-out流入该点,反之如果in<out,那么需要建立一条边流量为out-in流出该点,我们此时可以建立一个超级源和超级汇,此时我们在附加流上跑一遍最大流,如果从超级源出发的所有流量等于最大流,也就是说能保证流量守恒,那么就是有可行流,每条边的可行流等于该边的轮流下界+附加流中的流过的流量(既附加流中反向边的流量)

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200+10,maxn=40000+10,inf=0x3f3f3f;

struct edge{
    int from,to,Next,c,low;
}e[maxn<<2];
int cnt,head[N];
int dis[N],s,t;
int out[N],in[N];
void add(int u,int v,int c,int low)
{
    e[cnt].from=u;
    e[cnt].low=low;
    e[cnt].to=v;
    e[cnt].c=c;
    e[cnt].Next=head[u];
    head[u]=cnt++;
    e[cnt].from=v;
    e[cnt].low=low;
    e[cnt].to=u;
    e[cnt].c=0;
    e[cnt].Next=head[v];
    head[v]=cnt++;
}
bool bfs()
{
    memset(dis,-1,sizeof dis);
    dis[s]=0;
    queue<int>q;
    q.push(s);
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=head[x];~i;i=e[i].Next)
        {
            int te=e[i].to;
            if(e[i].c>0&&dis[te]==-1)
            {
                dis[te]=dis[x]+1;
                q.push(te);
            }
        }
    }
    return dis[t]!=-1;
}
int dfs(int x,int mx)
{
    if(x==t)return mx;
    int flow=0;
    for(int i=head[x];~i;i=e[i].Next)
    {
        int te=e[i].to,f;
        if(dis[te]==dis[x]+1&&e[i].c>0&&(f=dfs(te,min(mx-flow,e[i].c))))
        {
            e[i].c-=f;
            e[i^1].c+=f;
            flow+=f;
        }
    }
    if(!flow)dis[x]=-2;
    return flow;
}
int maxflow()
{
    int ans=0,f;
    while(bfs())
    {
        while((f=dfs(s,inf)))ans+=f;
    }
    return ans;
}
void init()
{
    cnt=0;
    memset(head,-1,sizeof head);
    memset(out,0,sizeof out);
    memset(in,0,sizeof in);
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        int n,m;
        cin>>n>>m;
        init();
        for(int i=0; i<m; i++)
        {
            int a,b,c,d;
            cin>>a>>b>>c>>d;
            out[a]+=c;
            in[b]+=c;
            add(a,b,d-c,c);
        }
        s=n+1,t=n+2;
        int sum=0;
        for(int i=1; i<=n; i++)
        {
            if(in[i]>out[i])sum+=in[i]-out[i],add(s,i,in[i]-out[i],0);
            else add(i,t,out[i]-in[i],0);
        }
        if(sum==maxflow())
        {
            cout<<"YES"<<endl;
            for(int i=0;i<2*m;i+=2)
                cout<<e[i^1].c+e[i].low<<endl;
        }
        else cout<<"NO"<<endl;
    }
    return 0;
}
/********************

********************/
View Code
原文地址:https://www.cnblogs.com/acjiumeng/p/7804159.html