看到AClist里面有dzy就知道是网络流 最后还是没想出来 只好找题解了Orz
基础知识
本题题解 其中那个y[i]前面应该是负号 作者打错了
判无解的时候是不满流 要用流量判 不要用费用判!!!!
膜拜此题Orz
#include
using namespace std;
const int maxn=2000 + 10, maxm=maxn*maxn*2;
const int maxl=999999999;
inline int Min(int a,int b){return a
inline int Max(int a,int b){return a>b?a:b;}
struct st
{
int y,d;
int ne;
int bro;
int f;
} e[maxm];
int ee;
int st[maxn];
int n,m;
void addedge(int x,int y,int d,int f)
{//给顶点x和y间添加一条费用d,流量f的边
e[ee].y=y;e[ee].d=d;e[ee].ne=st[x];e[ee].f=f;st[x]=ee++;
e[ee].y=x;e[ee].d=-1*d;e[ee].ne=st[y];e[ee].f=0;st[y]=ee++;
e[ee-2].bro=ee-1;e[ee-1].bro=ee-2;
}
int d[maxn],p[maxn];
//spfa所用到起点的最短距离(这里距离相当于cost)和路径记录之前的一个节点
int c[maxn];//spfa所用数组:是否在队列中
int que[maxn],head,tail;//spfa专用队列
int flow=0;
int spfa(int sx,int ex,int n)//求sx到ex的一次费用增广
{//如果没有增广路就返回maxl否则返回费用
int i,j,k;
for (i=0;i
memset(c,0,sizeof(c));//初始化都没进
d[sx]=0;
que[head=0]=sx;tail=1;
c[sx]=1;
while (head!=tail)//spfa开始
{
k=que[head++];head%=maxn;
c[k]=0;
for (i=st[k];i!=-1;i=e[i].ne) if (e[i].f)
if (d[k]+e[i].d
{
d[e[i].y]=d[k]+e[i].d;
p[e[i].y]=i;
if (c[e[i].y]==0)
{
c[e[i].y]=1;
if (e[i].d<0){head=(head-1+maxn)%maxn;que[head]=e[i].y;}
else
{que[tail++]=e[i].y;tail%=maxn;}
}
}
}
if (d[ex]==maxl) return maxl;//如果无法到达终点返回maxl
k=maxl;
for (i=ex;i!=sx;i=e[e[p[i]].bro].y) k=Min(k,e[p[i]].f);//计算流
for (i=ex;i!=sx;i=e[e[p[i]].bro].y)//增加反向边
{
e[p[i]].f-=k;
e[e[p[i]].bro].f+=k;
}
flow+=k;
return d[ex]*k;//返回费用为流大小*路径长度(cost累加)
}
int w[200],sumw[200];
int fa[200];
int ui[maxn],vi[maxn],li[maxn],ci[maxn];
int toto=0;
void init()
{
int i,j,k;
scanf("%d",&n);
for (i=1;i
{
scanf("%d%d",&j,&k);
fa[j]=k;
scanf("%d",w+j);
}
memset(st,-1,sizeof(st));
ee=0;
toto=0;
scanf("%d",&m);
for (i=1;i<=m;i++)
scanf("%d%d%d%d",ui+i,vi+i,li+i,ci+i);
for (j=1;j<=m;j++)
addedge(ui[j],vi[j],ci[j],li[j]);
for (i=2;i<=n;i++)
addedge(fa[i],i,0,maxl);
memset(sumw,0,sizeof(sumw));
for (i=2;i<=n;i++)
sumw[fa[i]]+=w[i];
w[1]=0;
for (i=1;i<=n;i++)
if (sumw[i]
{
addedge(0,i,0,w[i]-sumw[i]);
toto+=w[i]-sumw[i];
}
else
if (sumw[i]>w[i])
addedge(i,n+1,0,sumw[i]-w[i]);
}
int main()
{
int cass,cas=0;
for (scanf("%d",&cass);cass–;)
{
cas++;
init();
printf("Case #%d: ",cas);
int cost=0;
flow=0;
while (1)
{
int k=spfa(0,n+1,n+2);
if (k
cost+=k;
else
break;
}
if (flow
puts("-1");
else
printf("%dn",cost);
}
return 0;
}