zoukankan      html  css  js  c++  java
  • #115. 无源汇有上下界可行流(模板)

    题目描述

    这是一道模板题n  个点,m  条边,每条边 e  有一个流量下界 lower(e)(和流量上界 upper(e) ,求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。

    输入格式

    第一行两个正整数 n m

    之后的 m行,每行四个整数 s t lower upper

    输出格式

    如果无解,输出一行 NO

    否则第一行输出 YES,之后 m 行每行一个整数,表示每条边的流量。

    样例

    样例输入 1

    4 6
    1 2 1 2
    2 3 1 2
    3 4 1 2
    4 1 1 2
    1 3 1 2
    4 2 1 2

    样例输出 1

    NO

    样例输入 2

    4 6
    1 2 1 3
    2 3 1 3
    3 4 1 3
    4 1 1 3
    1 3 1 3
    4 2 1 3

    样例输出 2

    YES
    1
    2
    3
    2
    1
    1

    数据范围与提示

    1≤n≤200,1≤m≤10200 

    题解:

    模板题;其实可以就是通过某种建图,然后取跑最大流,可是否满流。

    具体建图方式: 建立源点S 汇点T, 每条边建立 x ->y,flow=(最大流)-(最小流),同时建立每个点流入流出情况d[i],即d[x]-=流出,d[y]+=流入,输出是最小流+跑完最大流后每条边上的流量。

    #include <bits/stdc++.h>
    using namespace std;
    const int MAXN=10200+10;
    const int MAXM=10200+10;
    const int INF=0x3f3f3f3f;
    int ss,tt;
    struct node{
        int v,next,flow;
    }edge[MAXN*10];
    int head[MAXN],cnt=0,cur[MAXN];
    int d[MAXN],st[MAXM];
    void ADD(int x,int y,int flow)
    {
        edge[cnt].v=y;
        edge[cnt].flow=flow;
        edge[cnt].next=head[x];
        head[x]=cnt++;
    
        edge[cnt].v=x;
        edge[cnt].flow=0;
        edge[cnt].next=head[y];
        head[y]=cnt++;
    }
    
    int dis[MAXN];
    bool bfs()
    {
        memset(dis,-1, sizeof(dis));
        queue<int >qu;
        while(!qu.empty())
            qu.pop();
        qu.push(ss);
        dis[ss]=0;
        int u,v;
        while (!qu.empty())
        {
            u=qu.front();
            qu.pop();
            for (int i = head[u]; i !=-1 ; i=edge[i].next) {
                v=edge[i].v;
                if(dis[v]==-1&&edge[i].flow>0)
                {
                    dis[v]=dis[u]+1;
                    qu.push(v);
                    if(v==tt)
                        break;
                }
            }
        }
        return dis[tt]!=-1;
    }
    int dfs(int u,int cap)
    {
        if(u==tt||cap==0)
            return cap;
        int res=0,v,f;
        for (int &i = cur[u]; i !=-1; i=edge[i].next) {
            v=edge[i].v;
            if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,edge[i].flow)))>0)
            {
                edge[i].flow-=f;
                edge[i^1].flow+=f;
                res+=f;
                if(res==cap)
                    return cap;
            }
        }
        if(!res)
            dis[u]=-1;
        return res;
    }
    
    int dinic()
    {
        int ans=0;
        while(bfs())
        {
            for (int i = 0; i <=tt ; ++i) {
                cur[i]=head[i];
            }
            ans+=dfs(ss,INF);
        }
        return ans;
    }
    
    
    
    int main()
    {
        int n,m;
        memset(head,-1, sizeof(head));
        memset(d,0, sizeof(d)); memset(st,0, sizeof(st));
        scanf("%d%d",&n,&m);
        ss=0;tt=n+1;
        int x,y,low,up;
        for (int i = 0; i <m ; ++i) {
            scanf("%d%d%d%d",&x,&y,&low,&up);
            ADD(x,y,up-low);
            d[x]-=low;
            d[y]+=low;
            st[i]=low;
        }
        int sum=0;
        for (int i = 1; i <=n ; ++i) {
            if(d[i]>0)
                sum+=d[i];
                ADD(ss,i,d[i]);
            if(d[i]<0)
                ADD(i,tt,-d[i]);
        }
        if(dinic()!=sum)
        {
            printf("NO
    ");
            return 0;
        } else
        {
            printf("YES
    ");
            for (int i = 0; i <m ; ++i) {
                printf("%d
    ",edge[i*2|1].flow+st[i]);
            }
        }
        return 0;
    }
    //loj115
    

      

  • 相关阅读:
    php AppStore内购付款验证
    NodeJS
    Electron 的中文乱码问题
    Flexbox 弹性盒子布局的使用
    springboot整合quartz
    第4章:逆向分析技术--64位软件逆向技术
    第51章:静态反调试技术——API查询
    第51章:静态反调试技术
    第48章:SEH
    第47章:PEB
  • 原文地址:https://www.cnblogs.com/-xiangyang/p/9773887.html
Copyright © 2011-2022 走看看