题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2314
输入:第一行包含数字N,节点的个数和M,管道的数量。接下来的M行包含4个整数,i,j,lij,cij。没有管道连接到自己。如果有一个管道从i连到j,那么就没有管道从j连到i

输出:如果有办法启动反应堆,第一行输出YES,否则,第一行输出NO。第一种情况下,将输出M个整数,第K个是第K个管道的液体量。

思路:无源汇有上下界网络的可行流模板题:https://blog.csdn.net/axuan_k/article/details/47282421。

流量可以通过反向边的流量得到。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e5+10;

struct E
{
    int v;   //每一条边指向的点
    int w;   //每一条边的残量
    int next;//指向对应点的前一条边

}e[maxm*2];

int s, t;
int cut;
int head[maxm];
int d[maxn];
int inf=(1<<31)-1;
int cur[maxn];
int id[maxm*2];
int dis[maxn];
int low[maxm];
int n, m;

void init()
{
    cut=-1;
    memset(dis, 0, sizeof(dis));
    memset(head, -1, sizeof(head));
}

void add(int u, int v, int w, int i)
{
    cut++;
    e[cut]=E{v, w, head[u]};
    head[u]=cut++;

    e[cut]=E{u, 0, head[v]};
    id[i]=head[v]=cut;
}

int bfs()
{
    queue<int> q;
    while(!q.empty())
    {
        q.pop();
    }
    memset(d, 0, sizeof(d));
    d[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v, w=e[i].w;
            if(w>0&&d[v]==0)
            {
                d[v]=d[u]+1;
                q.push(v);
            }
        }
    }
    if(d[t]==0)
    {
        return 0;
    }

    return 1;
}

int dfs(int u, int dis)
{
    if(u==t)
    {
        return dis;
    }

    for(int &i=cur[u];i!=-1;i=e[i].next)
    {
        int v=e[i].v, w=e[i].w;
        if((d[v]==d[u]+1)&&w!=0)
        {
            int di=dfs(v, min(dis, w));
            if(di>0)
            {
                e[i].w-=di;
                e[i^1].w+=di;
                return di;
            }
        }
    }

    return 0;
}

int Dinic()
{
    int ans=0;
    while (bfs())
    {
        for(int i=s;i<=t+1;i++)
        {
            cur[i]=head[i];
        }
        while (int d=dfs(s,inf))
        {
            ans+=d;
        }
    }
    return ans;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        scanf("%d%d",&n,&m);

        init();

        for(int i=1;i<=m;i++)
        {
            int u, v, l, p;
            scanf("%d%d%d%d",&u,&v,&low[i],&p);
            add(u, v, p-low[i], i);
            dis[u]-=low[i];
            dis[v]+=low[i];
        }

        int sum=0;
        for(int i=1;i<=n;i++)
        {
            if(dis[i]>0)
            {
                add(0, i, dis[i], 0);
                sum+=dis[i];
            }
            else
            {
                add(i, n+1, -dis[i], 0);
            }
        }
        s=0, t=n+1;
        if(Dinic()==sum)
        {
            printf("YES\n");
            for(int i=1;i<=m;i++)
            {
                printf("%d\n",low[i]+e[id[i]].w);
            }
        }
        else
        {
            cout<<"NO"<<endl;
        }
        cout<<endl;
    }

    return 0;
}