竞赛图一般是把每场比赛当作一个点,然后和相应球队连边
每场比赛一赢一输对两支球队都有影响看起来不好搞
实际上我们可以先假设参加后面后面所有球队都输(每场比赛双输)
然后对每场比赛我们选择一支球队赢计算增加的收益,这样就很简单了
下面就是经典的平方流的做法
1 const inf=2147483647; 2 type node=record 3 flow,next,cost,po:longint; 4 end; 5 6 var e:array[0..400010] of node; 7 q:array[0..1000010] of longint; 8 s,a,b,l,w,p,cur,pre,d:array[0..6010] of longint; 9 v:array[0..6010] of boolean; 10 ans,len,i,j,x,y,n,m,t:longint; 11 12 procedure add(x,y,f,c:longint); 13 begin 14 inc(len); 15 e[len].po:=y; 16 e[len].flow:=f; 17 e[len].cost:=c; 18 e[len].next:=p[x]; 19 p[x]:=len; 20 end; 21 22 procedure build(x,y,f,c:longint); 23 begin 24 add(x,y,f,c); 25 add(y,x,0,-c); 26 end; 27 28 function spfa:boolean; 29 var x,y,i,f,r:longint; 30 begin 31 f:=1; 32 r:=1; 33 q[1]:=0; 34 fillchar(v,sizeof(v),false); 35 for i:=1 to t do 36 d[i]:=inf; 37 d[0]:=0; 38 while f<=r do 39 begin 40 x:=q[f]; 41 v[x]:=false; 42 i:=p[x]; 43 while i<>-1 do 44 begin 45 y:=e[i].po; 46 if e[i].flow>0 then 47 if d[y]>d[x]+e[i].cost then 48 begin 49 cur[y]:=i; 50 pre[y]:=x; 51 d[y]:=d[x]+e[i].cost; 52 if not v[y] then 53 begin 54 inc(r); 55 q[r]:=y; 56 v[y]:=true; 57 end; 58 end; 59 i:=e[i].next; 60 end; 61 inc(f); 62 end; 63 if d[t]=inf then exit(false) else exit(true); 64 end; 65 66 function mincost:longint; 67 var i,j:longint; 68 begin 69 mincost:=0; 70 while spfa do 71 begin 72 mincost:=mincost+d[t]; 73 i:=t; 74 while i<>0 do 75 begin 76 j:=cur[i]; 77 dec(e[j].flow); 78 inc(e[j xor 1].flow); 79 i:=pre[i]; 80 end; 81 end; 82 end; 83 84 begin 85 len:=-1; 86 fillchar(p,sizeof(p),255); 87 readln(n,m); 88 for i:=1 to n do 89 readln(w[i],l[i],a[i],b[i]); 90 t:=n+m+1; 91 for i:=1 to m do 92 begin 93 readln(x,y); 94 inc(s[x]); 95 inc(s[y]); 96 build(0,i,1,0); 97 build(i,x+m,1,0); 98 build(i,y+m,1,0); 99 end; 100 for i:=1 to n do 101 begin 102 ans:=ans+a[i]*sqr(w[i])+b[i]*sqr(s[i]+l[i]); 103 for j:=1 to s[i] do 104 build(i+m,t,1,(a[i]+b[i])*(2*j-1)+2*w[i]*a[i]-2*b[i]*(s[i]+l[i])); 105 end; 106 writeln(mincost+ans); 107 end.