#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\n");
        return 0;
    } else
    {
        printf("YES\n");
        for (int i = 0; i <m ; ++i) {
            printf("%d\n",edge[i*2|1].flow+st[i]);
        }
    }
    return 0;
}
//loj115

  

 

posted @ 2018-10-11 17:35  岩扉  阅读(520)  评论(0编辑  收藏  举报