版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a1046765624/article/details/82941654
题目描述
这是一道模板题。
n nn 个点,m mm 条边,每条边 e ee 有一个流量下界 lower(e) \text{lower}(e)lower(e) 和流量上界 upper(e) \text{upper}(e)upper(e),求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。
输入格式
第一行两个正整数 n nn、m mm。
之后的 m mm 行,每行四个整数 s ss、t tt、lower \text{lower}lower、upper \text{upper}upper。
输出格式
如果无解,输出一行 NO
。
否则第一行输出 YES
,之后 m mm 行每行一个整数,表示每条边的流量。
样例
样例输入 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 1 \leq n \leq 200, 1 \leq m \leq 102001≤n≤200,1≤m≤10200
代码:
#include <bits/stdc++.h>
using namespace std ;
#define copy( a , x ) memcpy ( a , x , sizeof a )
typedef long long LL ;
const int MAXN = 15000 ;
const int MAXE = 100000 ;
const int MAXQ = 100000 ;
const int INF = 0x3f3f3f3f ;
struct Edge {
int v , n ;
LL c ;
Edge ( int var = 0 , LL cap = 0 , int next = 0 ) :
v ( var ) , c ( cap ) , n ( next ) {}
} ;
struct netWork {
Edge edge[MAXE] ;
int adj[MAXN] , cntE ;
int cur[MAXN] , d[MAXN] , num[MAXN] , pre[MAXN] ;
bool vis[MAXN] ;
int Q[MAXQ] , head , tail ;
int s , t , nv ;
LL flow ;
void init () {
cntE = 0 ;
memset(adj,-1,sizeof(adj));
}
void addedge ( int u , int v , LL c , LL rc = 0 ) {
edge[cntE] = Edge ( v , c , adj[u] ) ;
adj[u] = cntE ++ ;
edge[cntE] = Edge ( u , rc , adj[v] ) ;
adj[v] = cntE ++ ;
}
void rev_Bfs () {
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
d[t] = 0 ;
vis[t] = 1 ;
head = tail = 0 ;
Q[tail ++] = t ;
num[0] = 1 ;
while ( head != tail ) {
int u = Q[head ++] ;
for ( int i = adj[u] ; ~i ; i = edge[i].n ) {
int v = edge[i].v ;
if ( vis[v] )
continue ;
vis[v] = 1 ;
d[v] = d[u] + 1 ;
++ num[d[v]] ;
Q[tail ++] = v ;
}
}
}
LL ISAP () {
copy ( cur , adj ) ;
rev_Bfs () ;
flow = 0 ;
int i , u = pre[s] = s ;
while ( d[s] < nv ) {
if ( u == t ) {
LL f = INF ;
int pos ;
for ( i = s ; i != t ; i = edge[cur[i]].v )
if ( f > edge[cur[i]].c )
f = edge[cur[i]].c , pos = i ;
for ( i = s ; i != t ; i = edge[cur[i]].v )
edge[cur[i]].c -= f , edge[cur[i] ^ 1].c += f ;
u = pos ;
flow += f ;
}
for ( i = cur[u] ; ~i ; i = edge[i].n )
if ( edge[i].c && d[u] == d[edge[i].v] + 1 )
break ;
if ( ~i ) {
cur[u] = i ;
pre[edge[i].v] = u ;
u = edge[i].v ;
}
else {
if ( 0 == ( -- num[d[u]] ) )
break ;
int mmin = nv ;
for ( i = adj[u] ; ~i ; i = edge[i].n )
if ( edge[i].c && mmin > d[edge[i].v] )
cur[u] = i , mmin = d[edge[i].v] ;
d[u] = mmin + 1 ;
++ num[d[u]] ;
u = pre[u] ;
}
}
return flow ;
}
} ;
netWork net ;
int pp;
int n,m,k;
LL to[MAXN];
int ss,tt;
int L[MAXN],R[MAXN];
int fb[MAXN];
void work () {
net.init () ;
memset(to,0,sizeof(to));
memset(fb,0,sizeof(fb));
net.s = n+1, net.t = net.s+1, net.nv = net.t + 1 ;
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&u,&v,&L[i],&R[i]);
net.addedge(u,v,R[i]-L[i]);
to[u]-=L[i];
to[v]+=L[i];
fb[i]=net.cntE-1;
}
LL sum=0;
for(int i=1;i<=n;i++)
{
if(to[i]>0)
{
net.addedge(net.s,i,to[i]);
sum+=to[i];
}
else
{
net.addedge(i,net.t,-to[i]);
}
}
LL flow =net.ISAP();
if(flow!=sum)
{
printf ("NO\n");
return;
}
printf ("YES\n");
for(int i=1;i<=m;i++)
{
printf("%lld\n",net.edge[fb[i]].c+L[i]);
}
}
int main()
{
scanf("%d%d",&n,&m);
work();
return 0;
}