Bzoj1449 [JSOI2009]球队收益

时间:2021-02-21 22:40:20

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 741  Solved: 423

Description

Bzoj1449 [JSOI2009]球队收益

Input

Bzoj1449 [JSOI2009]球队收益

Output

一个整数表示联盟里所有球队收益之和的最小值。

Sample Input

3 3
1 0 2 1
1 1 10 1
0 1 3 3
1 2
2 3
3 1

Sample Output

43

HINT

Bzoj1449 [JSOI2009]球队收益

Source

最小费用最大流。

  比赛无论胜负都会给球队带来收益,使得建边极为困难。考虑转化问题,首先假设每场比赛的结果是“两方都输”,以此为初始状态,之后决策某个队伍胜利,则获得的收益为“赢的收益-输的收益”。

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
const int INF=1e8;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct edge{
int from,v,nxt;
int f,w;
}e[mxn<<];
int hd[mxn],mct=;//
void add_edge(int u,int v,int c,int w){
e[++mct].v=v;e[mct].from=u;e[mct].nxt=hd[u];e[mct].f=c;e[mct].w=w;hd[u]=mct;return;
}
//
int n,m;
int S,T;
int ans=;
int win[mxn],lose[mxn],c[mxn],d[mxn];
//
int dis[mxn];
bool inq[mxn];
int pre[mxn<<];
void SPFA(int s){
memset(dis,0x3f,sizeof dis);
memset(pre,-,sizeof pre);
queue<int>q;
dis[s]=;
inq[s]=;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();inq[u]=;
for(int i=hd[u];i;i=e[i].nxt){
if(!e[i].f)continue;
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w){
dis[v]=dis[u]+e[i].w;
pre[v]=i;//记录前驱边
if(!inq[v]){
inq[v]=;
q.push(v);
}
}
}
}
return;
}
void maxflow(int s,int t){
SPFA(s);
while(pre[t]!=-){
int tmp=INF;
for(int i=pre[t];i!=-;i=pre[e[i].from])
tmp=min(tmp,e[i].f);
ans+=dis[t]*tmp;
for(int i=pre[t];i!=-;i=pre[e[i].from]){
e[i].f-=tmp;
e[i^].f+=tmp;
}
SPFA(s);
}
return;
}
int a[mxn],b[mxn];
int main()
{
int i,j,u,v;
n=read();m=read();
for(i=;i<=n;i++){
win[i]=read();lose[i]=read();
c[i]=read();d[i]=read();
}
for(i=;i<=m;i++){
a[i]=read();b[i]=read();
++lose[a[i]];++lose[b[i]];
}
for(i=;i<=n;i++){//假设全部都输掉
ans+=c[i]*win[i]*win[i];
ans+=d[i]*lose[i]*lose[i];
}
S=;T=m+n+;
for(i=;i<=m;i++){
add_edge(S,i,,);
add_edge(i,S,,);
add_edge(i,m+a[i],,);
add_edge(m+a[i],i,,);
add_edge(i,m+b[i],,);
add_edge(m+b[i],i,,);
//a
int cost=c[a[i]]*(*win[a[i]]+)-d[a[i]]*(*lose[a[i]]-);
add_edge(m+a[i],T,,cost);
add_edge(T,m+a[i],,-cost);
win[a[i]]++;lose[a[i]]--;
//b
cost=c[b[i]]*(*win[b[i]]+)-d[b[i]]*(*lose[b[i]]-);
add_edge(m+b[i],T,,cost);
add_edge(T,m+b[i],,-cost);
win[b[i]]++;lose[b[i]]--;
}
maxflow(S,T);
printf("%d\n",ans);
return ;
}