有源汇有上下界的最小流(LOJ117)

一个有源汇有上下界的最小流的瞎那啥讲解

其实最小流和最大流个人感觉很类似,连接了超级源点和超级汇点之后跑完一次最大流,一个是再在除去超级源点和超级汇点跑一次最大流,一个是给源汇点连一个无限边求最大流,然后无限边的流量就是答案

因为一个相当于是要把残量网络剩下的流加起来,才是最大流,而这个跑过最大流后剩下的就是最小流了

代码好像是有点点问题的,LOJ117上一直死跑不过第八个点,但本机上好像是能出正确答案的。。。

管他的反正也就一个点而已(作为一个蒟蒻能写成这样已经十分满足了,真的菜是没办法的)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll inf=1e15;
int str,des,cnt=1,adj[50050],nxt[500050],to[500050],lev[50050],low[500050],st,de,m,n;
ll def[50050],cap[500050];
inline int read(){
    char ch;
    while((ch=getchar())<'0'||ch>'9'){;}
    int res=ch-'0';
    while((ch=getchar())>='0'&&ch<='9')
    res=res*10+ch-'0';
    return res;
}
inline void addedge(int u,int v,long long p)
{
    nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,cap[cnt]=p;
    nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,cap[cnt]=0;
}
inline bool bfs(){
    int u,e,v;
    queue<int> que;
    memset(lev,-1,sizeof(lev));
    que.push(str),lev[str]=0;
    while(!que.empty())
    {
        u=que.front(),que.pop();
        for(int e=adj[u];e;e=nxt[e])
        {
            if(cap[e]>0&&lev[v=to[e]]==-1)
            {
                lev[v]=lev[u]+1,que.push(v);
                if(v==des) return true;
            }
        }
    }
    return false;
}
inline long long dinic( int u,ll flow)
{
    if(u==des) return flow;
    ll res=0,flw;
    int v;
    for(int e=adj[u];e;e=nxt[e])
    {
        if(cap[e]>0&&lev[u]<lev[v=to[e]])
        {
            flw=dinic(v,min(cap[e],flow-res));
            if(flw==0) lev[v]=-1;
            cap[e]-=flw,cap[e^1]+=flw;
            res+=flw;if(res==flow) break;
        }
    }
    return res;
}
inline long long  solve(){
    long long ans=0;
    while(bfs()==true) ans+=dinic(str,inf);
    return ans;
}
int main(){
    n=read(),m=read(),st=read(),de=read();
    int s,t;
    ll up,down;
    long long sum=0;
    for(int i=1;i<=m;i++)
    {
        s=read(),t=read(),down=read(),up=read();
        addedge(s,t,up-down);
        low[i]=down,def[s]+=down,def[t]-=down;
    }
    str=0,des=n+1;
    for(int i=1;i<=n;i++)
    {
        if(def[i]>0) addedge(i,des,def[i]);
        if(def[i]<0) addedge(str,i,-def[i]);
    }
    sum=solve();
    addedge(de,st,inf);
    sum+=solve();
    for(int e=adj[des];e;e=nxt[e]) 
    {
        if(cap[e^1]>0)
        {
            cout<<"please go home to sleep"<<'
';
            return 0;
        }
    }
    cout<<cap[cnt];
    return 0;
}
原文地址:https://www.cnblogs.com/forever-/p/9736085.html