算法:
新建一个源点汇点 st,en,对原来的每个点i,设m(i)=流入i点的流量下限fin-流出i点的流量下限fout,若m(i)>0,连一条<s,i>容量为m(i)的边;若m(i)<0,连一条<i,t>容量为-m(i)的边。然后将原来边的容量变为c<i,j>-b<i,j>,b<i,j>为流量下届。求一次最大流。如果与s和t关联的边全部满流,则可行流存在,且每条边的流量为现在的流量+流量的下界。否则不存在可行流。
我写了一早上,用我的Dinic模板第一次过不了网络流的题(o(╯□╰)o其实我也只做过几道网络流的题啦)
Dinic算法超时,加输入优化还是TLE!
然后改EK算法,加输入优化还是TLE!无奈之下去掉输入优化试一发,诶。。。A了。。。。
纪念一下第一道有上下界的网络流!
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 210
#define maxm 40010
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int to,v,next;
}e[maxm<<2];
int head[maxn],cnt,maxflow[maxn],flow[maxn][maxn],fin[maxn],fout[maxn];
int st,en,n,full,m,fa[maxn],l[maxm],a[maxm],b[maxm];
void add(int x,int y,int z)
{
e[cnt].to = y;
e[cnt].v = z;
e[cnt].next = head[x];
head[x] = cnt++;
e[cnt].to = x;
e[cnt].v = 0;
e[cnt].next = head[y];
head[y] = cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
cnt = 0;
st = 0;
en = n+1;
memset(fin,0,sizeof(fin));
memset(fout,0,sizeof(fout));
full = 0;
}
int EK()
{
int mf = 0;
memset(flow,0,sizeof(flow));
while(1)
{
queue<int> q;
memset(maxflow,0,sizeof(maxflow));
maxflow[st] = INF;
q.push(st);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v = e[i].to;
if(!maxflow[v] && e[i].v>flow[u][v])
{
fa[v] = u;
maxflow[v] = min(maxflow[u],e[i].v-flow[u][v]);
q.push(v);
}
}
}
if(maxflow[en]==0)
break;
for(int i=en;i!=st;i=fa[i])
{
flow[fa[i]][i]+=maxflow[en];
flow[i][fa[i]]-=maxflow[en];
}
mf+=maxflow[en];
}
return mf;
}
void solve()
{
int mf = EK();
if(mf!=full)
printf("NO\n");
else
{
printf("YES\n");
for(int i=0;i<m;i++)
printf("%d\n",flow[a[i]][b[i]]+l[i]);
}
}
int main()
{
int T,c;
char d;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
init();
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&a[i],&b[i],&l[i],&c);
add(a[i],b[i],c-l[i]);
fin[b[i]]+=l[i];
fout[a[i]]+=l[i];
}
for(int i=1;i<=n;i++)
{
int tmp = fin[i]-fout[i];
if(tmp>0)
{
add(st,i,tmp);
full += tmp;
}
else
add(i,en,-tmp);
}
solve();
}
return 0;
}