ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【图论】无源汇上下界可行/最大流

2020-09-06 15:32:40  阅读:419  来源: 互联网

标签:图论 int 源点 flow 流量 无源 dis 汇上 out



无源汇上下界可行/最大流

可行流即对于一张无源点与汇点的流量网络\(G\)

询问是否存在一种流量方案,使得每条边的流量在对应的上下界内,且每个点流量平衡

最大流则是在可行流的基础上求出最大流量




解法

既然对于流量网络\(G\)内每一条边的流量都进行了限制,使其必须处于\([L_i,R_i]\)之内

那么就假设每条边一开始就存在着要求的最小流量\(L_i\)

这条边此时的容量便变成了\(R_i-L_i\),初始流量为\(0\),以此初步建立流量网络

这样处理便解决了上下界的限制

但同时也导致每个点的流量不一定平衡,即流入量≠流出量

所以接下来要对点进行平衡处理,使得每条边与原图中对应的边相加后,全图流量平衡

构建虚拟源点\(S\)与虚拟汇点\(T\),使得能够虚拟提供流量

由于上面我们处理时使得每条边都固定拥有了流量\(L_i\)

那么对于这条边连接的两个点\(u_i,v_i\)

即\(u_i\)的流出量\(out[u_i]+=L_i\),\(v_i\)的流入量\(in[v_i]+=L_i\)

处理完所有边后,得到每个点的总流入量与总流出量

可得,如果对于点\(i\)

\(in[i]>=out[i]\):该点流入量较流出量大,说明点\(i\)需要多向外输出\(in[i]-out[i]\)的流量,那么这些流量就从虚拟源点\(S\)取,故建立\(S\)至\(i\)的流量为\(in[i]-out[i]\)的一条边

\(in[i]<out[i]\):该点流出量较流入量大,说明外面需要多向点\(i\)输入\(out[i]-in[i]\)的流量,换言之可以将该点多余的流量流向虚拟汇点\(T\),故建立\(i\)至\(T\)的流量为\(out[i]-in[i]\)的一条边



可行流求解

如上建立流量网络

可知,对于与源点/汇点连接的边的容量和代表着全图的流量总和

令所有\(in[i]>=out[i]\)情况下的\(in[i]-out[i]\)总和为\(sum\)(或所有\(in[i]<out[i]\)情况下的\(out[i]-in[i]\)总和)

对于这个流量网络,只有当最大流量流满\(sum\)时,才能做到全图的流量平衡

所以直接跑Dinic​,判断最大流是否等于\(sum\)即可



最大流求解

如上,采用Dinic算法跑出来的图即代表着最大流




例题

ZOJ 2314 Reactor Cooling

模板题,多组数据,给定点数与边数,给出每条边连向即上下界,问一种使得流量平衡的可行解

最后取出跑最大流后每条边对应的反向边流量作为该边的流量,加上初始的流量下界作为该边最终流量即可

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;

const int maxn=200,maxm=40000;
struct edge{
    int u,v,cap,flow;
    edge(){}
    edge(int u,int v,int cap,int flow):u(u),v(v),cap(cap),flow(flow){}
}eg[maxm<<1];
int tot,s,t,dis[maxn<<1],cur[maxn<<1];
vector<int> tab[maxn<<1];

void init(int n,int s_,int t_){
    while(n)tab[n--].clear();
    tot=0,s=s_,t=t_;
}
void addedge(int u,int v,int cap){
    tab[u].push_back(tot);
    eg[tot++]=edge(u,v,cap,0);
    tab[v].push_back(tot);
    eg[tot++]=edge(v,u,0,0);
}
int bfs(){
    queue<int> q;
    q.push(s);
    memset(dis,INF,sizeof dis);
    dis[s]=0;
    while(!q.empty()){
        int h=q.front(),i;
        q.pop();
        for(i=0;i<tab[h].size();i++){
            edge &e=eg[tab[h][i]];
            if(e.cap>e.flow&&dis[e.v]==INF){
                dis[e.v]=dis[h]+1;
                q.push(e.v);
            }
        }
    }
    return dis[t]<INF;
}
int dfs(int x,int maxflow){
    if(x==t|maxflow==0)
        return maxflow;
    int flow=0,i,f;
    for(i=cur[x];i<tab[x].size();i++){
        cur[x]=i;
        edge &e=eg[tab[x][i]];
        if(dis[e.v]==dis[x]+1&&(f=dfs(e.v,min(maxflow,e.cap-e.flow)))>0){
            e.flow+=f;
            eg[tab[x][i]^1].flow-=f;
            flow+=f;
            maxflow-=f;
            if(maxflow==0)
                break;
        }
    }
    return flow;
}
int dinic(){
    int flow=0;
    while(bfs()){
        memset(cur,0,sizeof(cur));
        flow+=dfs(s,INF);
    }
    return flow;
}

struct node
{
    int u,v,l,r;
}E[maxm<<1];
int in[maxn],out[maxn];

void solve()
{
    int n,m,u,v,sum=0;
    scanf("%d%d",&n,&m);
    init(n+2,n+1,n+2);
    for(int i=1;i<=n;i++)
        in[i]=out[i]=0;
    
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&E[i].u,&E[i].v,&E[i].l,&E[i].r);
        in[E[i].v]+=E[i].l;
        out[E[i].u]+=E[i].l;
        addedge(E[i].u,E[i].v,E[i].r-E[i].l); //限制流量为r-l
    }
    for(int i=1;i<=n;i++)
    {
        if(in[i]>=out[i])
            addedge(s,i,in[i]-out[i]),sum+=in[i]-out[i];
        else
            addedge(i,t,out[i]-in[i]);
    }
    
    if(dinic()<sum)
    {
        puts("NO");
        return;
    }
    puts("YES");
    for(int i=1;i<2*m;i+=2)
        printf("%d\n",E[i/2+1].l+eg[i^1].flow); //从跑出的残量网络中取反向边的flow为当前最大流量,加上原先的下界作为流量
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
        solve();
    return 0;
}

标签:图论,int,源点,flow,流量,无源,dis,汇上,out
来源: https://www.cnblogs.com/stelayuri/p/13621856.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有