/* 无源汇上下界最大流
对于有流量上下限的无源的网络流的可行流转化为一般的有源汇点的最大流来做
(1)添加超级源点s和超级汇点t
(2)对于原有的边(u,v,l(u,v),c(u,v))(l为流量下限,c为流量上限),添加边(u,v,0,c-l);
(3)对于每个结点i,记w[i]=l(u,i)-l(i,v)=f(i,v)-f(u,i);出-入
若w[i]>0,添加边(S,i,w[i]),若w[i]<0,添加边(i,T,-w[i]);
(4)求解s-t的最大流;
(5)当且仅当s的出边和t的入边满流,原流量限制的无源网络流可行流有解; 实际上判断其中一个条件即可。
(6)一组可行流的解为:
对于每条流量边(u,v),可行流量为l(u,v)+其构造的图中的流量.
*/
#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN=200000;
const int maxn=300;
struct EDGE
{
int from,to,next,flow;
}edge[MAXN];
int head[maxn],cnt;
int s,t,tot,sum;
int pre[maxn];
int gap[maxn];
int cur[maxn];
int level[maxn];
int w[maxn],l[MAXN];
inline void add(int u,int v,int flow)
{
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].flow=flow;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].from=v;
edge[cnt].to=u;
edge[cnt].flow=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void build_graph(int n,int m)
{
s=0,t=n+1,tot=n+2,cnt=0; //(1)添加超级源点s和超级汇点t
memset(pre,-1,sizeof(pre));
memset(gap,0,sizeof(gap));
memset(level,0,sizeof(level));
memset(head,-1,sizeof(head));
gap[0]=tot;
for(int i=0;i<m;i++)
{
int u,v,c;
scanf("%d%d%d%d",&u,&v,&l[i],&c);//因为上界暂不需要,不需要储存
add(u,v,c-l[i]);//(2)对于原有的边(u,v,l(u,v),c(u,v))(l为流量下限,c为流量上限),添加边(u,v,0,c-l);
w[u]-=l[i]; //w[i]=l(u,i)-l(i,v)
w[v]+=l[i];
}
for(int i=1;i<=n;i++) //若w[i]>0,添加边(S,i,w[i]),若w[i]<0,添加边(i,T,-w[i]);
{
if(w[i]>0) add(s,i,w[i]);//f(u,i)+w[i]=f(i,v)
if(w[i]<0) add(i,t,-w[i]),sum+=-w[i];//f(u,i)=f(i,v)+w[i]
}
}
int sap()
{
int u=s,ans=0,inf=INT_MAX;
for(int i=0;i<tot;i++)
cur[i]=head[i];
while(level[s]<tot)
{
bool flag=0;
for(int &i=cur[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].flow>0&&level[u]==level[v]+1)
{
flag=1;
if(edge[i].flow<inf)
inf=edge[i].flow;
pre[v]=u;
u=v;
if(u==t)
{
while(u!=s)
{
u=pre[u];
edge[cur[u]].flow-=inf;
edge[cur[u]^1].flow+=inf;
}
ans+=inf;
inf=INT_MAX;
}
break;
}
}
if(!flag)
{
if(--gap[level[u]]==0)
break;
int minn=tot;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].flow>0&&level[v]<minn)
{
minn=level[v];
cur[u]=i;
}
}
level[u]=minn+1;
gap[minn+1]++;
if(u!=s)
u=pre[u];
}
}
return ans;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
build_graph(n,m);
if(sap()!=sum)
printf("NO\n");
else
{
printf("YES\n");
for (int i=0; i<m; i++) //对于每条流量边(u,v),可行流量为l(u,v)+其构造的图中的流量.
printf("%d\n",edge[i*2+1].flow+l[i]);//前2*m都是原数据的边,edge[2*i+1].flow为构造图的流量
}
return 0;
}