首页 > 代码库 > Bzoj1449 [JSOI2009]球队收益

Bzoj1449 [JSOI2009]球队收益

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

Description

技术分享

Input

技术分享

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

技术分享

Source

 

最小费用最大流。

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

  1 #include<iostream>  2 #include<cstdio>  3 #include<algorithm>  4 #include<cmath>  5 #include<queue>  6 #include<cstring>  7 using namespace std;  8 const int INF=1e8;  9 const int mxn=9000; 10 int read(){ 11     int x=0,f=1;char ch=getchar(); 12     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();} 13     while(ch>=0 && ch<=9){x=x*10+ch-0;ch=getchar();} 14     return x*f; 15 } 16 struct edge{ 17     int from,v,nxt; 18     int f,w; 19 }e[mxn<<1]; 20 int hd[mxn],mct=1;// 21 void add_edge(int u,int v,int c,int w){ 22     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; 23 } 24 // 25 int n,m; 26 int S,T; 27 int ans=0; 28 int win[mxn],lose[mxn],c[mxn],d[mxn]; 29 // 30 int dis[mxn]; 31 bool inq[mxn]; 32 int pre[mxn<<1]; 33 void SPFA(int s){ 34     memset(dis,0x3f,sizeof dis); 35     memset(pre,-1,sizeof pre); 36     queue<int>q; 37     dis[s]=0; 38     inq[s]=1; 39     q.push(s); 40     while(!q.empty()){ 41         int u=q.front();q.pop();inq[u]=0; 42         for(int i=hd[u];i;i=e[i].nxt){ 43             if(!e[i].f)continue; 44             int v=e[i].v; 45             if(dis[v]>dis[u]+e[i].w){ 46                 dis[v]=dis[u]+e[i].w; 47                 pre[v]=i;//记录前驱边  48                 if(!inq[v]){ 49                     inq[v]=1; 50                     q.push(v); 51                 } 52             } 53         } 54     } 55     return; 56 } 57 void maxflow(int s,int t){ 58     SPFA(s); 59     while(pre[t]!=-1){ 60         int tmp=INF; 61         for(int i=pre[t];i!=-1;i=pre[e[i].from]) 62             tmp=min(tmp,e[i].f); 63         ans+=dis[t]*tmp; 64         for(int i=pre[t];i!=-1;i=pre[e[i].from]){ 65             e[i].f-=tmp; 66             e[i^1].f+=tmp; 67         } 68         SPFA(s); 69     } 70     return; 71 } 72 int a[mxn],b[mxn]; 73 int main() 74 { 75     int i,j,u,v; 76     n=read();m=read(); 77     for(i=1;i<=n;i++){ 78         win[i]=read();lose[i]=read(); 79         c[i]=read();d[i]=read(); 80     } 81     for(i=1;i<=m;i++){ 82         a[i]=read();b[i]=read(); 83         ++lose[a[i]];++lose[b[i]]; 84     } 85     for(i=1;i<=n;i++){//假设全部都输掉  86         ans+=c[i]*win[i]*win[i]; 87         ans+=d[i]*lose[i]*lose[i]; 88     } 89     S=0;T=m+n+2; 90     for(i=1;i<=m;i++){ 91         add_edge(S,i,1,0); 92         add_edge(i,S,0,0); 93         add_edge(i,m+a[i],1,0); 94         add_edge(m+a[i],i,0,0); 95         add_edge(i,m+b[i],1,0); 96         add_edge(m+b[i],i,0,0); 97         //a 98         int cost=c[a[i]]*(2*win[a[i]]+1)-d[a[i]]*(2*lose[a[i]]-1); 99         add_edge(m+a[i],T,1,cost);100         add_edge(T,m+a[i],0,-cost);101         win[a[i]]++;lose[a[i]]--;102         //b103         cost=c[b[i]]*(2*win[b[i]]+1)-d[b[i]]*(2*lose[b[i]]-1);104         add_edge(m+b[i],T,1,cost);105         add_edge(T,m+b[i],0,-cost);106         win[b[i]]++;lose[b[i]]--;107     }108     maxflow(S,T);109     printf("%d\n",ans);110     return 0;111 }

 

Bzoj1449 [JSOI2009]球队收益