题面 点击打开链接
球队的收益随场数递增 (tot球队参加的总比赛数)
先假设以后的比赛全输
赢一场收益S1=Ci*(win1+1)^2+Di(losei+tot-1)^2;
赢二场S2=Ci*(win1+2)^2+Di(losei+tot-2)^2;
****
x场Ci*(win1+x)^2+Di(losei+tot-x)^2;
根据上面的式子
赢第一场增加的收益=S1-ci*win1^2+di*(losei+tot)^2;
赢第二场增加的收益=S2-S1
****
赢第x场=ci*(2*win+2*x-1)-di(2*tot+2*lose-2*x+1)
从源点向n个队建边,向第i个点见tot[i]条边,第i条边权值为Si-Si-1
每个队向参加的比赛连边,f=1,c=0;
每场比赛向汇点连边,f=1,c=0;
跑一遍最大流最小花费
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 5005
using namespace std;
int n,m,cnt=0,cost=0,sum=0;
int w[N],l[N],c[N],d[N];
int a[N];
struct edge
{
int fr,to,ne,w,co;
}b[N*200];
int head[N+1005],k=0;
void add(int u,int v,int w,int c)
{
edge E1={u,v,head[u],w,c};
b[k]=E1; head[u]=k++;
edge E2={v,u,head[v],0,-c};
b[k]=E2; head[v]=k++;
}
inline void read()
{
int x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d%d%d%d",&w[i],&l[i],&c[i],&d[i]);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
add(x,n+i,1,0);
add(y,n+i,1,0);
a[x]++; a[y]++;
}
for(int i=1;i<=n;i++){
sum+=c[i]*w[i]*w[i]+d[i]*(a[i]+l[i])*(a[i]+l[i]);
}
}
void build()
{
cnt=n+m+1;
int t=0;
for(int i=1;i<=n;i++){
add(0,i,0,0);
for(int j=1;j<=a[i];j++){
t=c[i]*(2*w[i]+2*j-1)-d[i]*(2*a[i]+2*l[i]-2*j+1);
add(0,i,1,t);
}
}
for(int i=1;i<=m;i++)
add(n+i,cnt,1,0);
}
int dis[N+1005],vis[N+1005],pr[N+1005],cc[N+1005];
bool spfa()
{
memset(dis,0xf,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(pr,-1,sizeof(pr));
memset(cc,0,sizeof(cc));
queue<int> q;
q.push(0);vis[0]=1;dis[0]=0;cc[0]=0x7fffffff;
while(!q.empty())
{
int z=q.front();q.pop();vis[z]=0;
for(int i=head[z];i!=-1;i=b[i].ne)
if(b[i].w&&dis[b[i].to]>dis[z]+b[i].co)
{
dis[b[i].to]=dis[z]+b[i].co;
pr[b[i].to]=i;
cc[b[i].to]=min(b[i].w,cc[z]);
if(vis[b[i].to]==0){
vis[b[i].to]=1;
q.push(b[i].to);
}
}
}
return pr[cnt]!=-1;
}
void mcmf()
{
cost+=dis[cnt]*cc[cnt];
int w=cnt;
while(w!=0){
b[pr[w]].w-=cc[cnt];
b[pr[w]^1].w+=cc[cnt];
w=b[pr[w]].fr;
}
}
int main()
{
//freopen("in.txt","r",stdin);
memset(head,-1,sizeof(head));
read();
build();
while(spfa()==1) mcmf();
cost=sum+cost;
printf("%d",cost);
// while(1);
return 0;
}