竞赛图一般是把每场比赛当作一个点,然后和相应球队连边
每场比赛一赢一输对两支球队都有影响看起来不好搞
实际上我们可以先假设参加后面后面所有球队都输(每场比赛双输)
然后对每场比赛我们选择一支球队赢计算增加的收益,这样就很简单了
下面就是经典的平方流的做法
const inf=;
type node=record
flow,next,cost,po:longint;
end; var e:array[..] of node;
q:array[..] of longint;
s,a,b,l,w,p,cur,pre,d:array[..] of longint;
v:array[..] of boolean;
ans,len,i,j,x,y,n,m,t:longint; procedure add(x,y,f,c:longint);
begin
inc(len);
e[len].po:=y;
e[len].flow:=f;
e[len].cost:=c;
e[len].next:=p[x];
p[x]:=len;
end; procedure build(x,y,f,c:longint);
begin
add(x,y,f,c);
add(y,x,,-c);
end; function spfa:boolean;
var x,y,i,f,r:longint;
begin
f:=;
r:=;
q[]:=;
fillchar(v,sizeof(v),false);
for i:= to t do
d[i]:=inf;
d[]:=;
while f<=r do
begin
x:=q[f];
v[x]:=false;
i:=p[x];
while i<>- do
begin
y:=e[i].po;
if e[i].flow> then
if d[y]>d[x]+e[i].cost then
begin
cur[y]:=i;
pre[y]:=x;
d[y]:=d[x]+e[i].cost;
if not v[y] then
begin
inc(r);
q[r]:=y;
v[y]:=true;
end;
end;
i:=e[i].next;
end;
inc(f);
end;
if d[t]=inf then exit(false) else exit(true);
end; function mincost:longint;
var i,j:longint;
begin
mincost:=;
while spfa do
begin
mincost:=mincost+d[t];
i:=t;
while i<> do
begin
j:=cur[i];
dec(e[j].flow);
inc(e[j xor ].flow);
i:=pre[i];
end;
end;
end; begin
len:=-;
fillchar(p,sizeof(p),);
readln(n,m);
for i:= to n do
readln(w[i],l[i],a[i],b[i]);
t:=n+m+;
for i:= to m do
begin
readln(x,y);
inc(s[x]);
inc(s[y]);
build(,i,,);
build(i,x+m,,);
build(i,y+m,,);
end;
for i:= to n do
begin
ans:=ans+a[i]*sqr(w[i])+b[i]*sqr(s[i]+l[i]);
for j:= to s[i] do
build(i+m,t,,(a[i]+b[i])*(*j-)+*w[i]*a[i]-*b[i]*(s[i]+l[i]));
end;
writeln(mincost+ans);
end.