球队预算
Time Limit: 10 Sec Memory Limit: 256 MB
[Submit][Status][Discuss]
Description
在一个篮球联赛里,有n支球队,
球队的支出是和他们的胜负场次有关系的,具体来说,第i支球队的赛季总支出是Ci*x^2+Di*y^2,Di<=Ci。(赢得多,给球员的奖金就多嘛)
其中x,y分别表示这只球队本赛季的胜负场次。
现在赛季进行到了一半,每只球队分别取得了a[i]场胜利和b[i]场失利。
而接下来还有m场比赛要进行。
问联盟球队的最小总支出是多少。
Input
第一行n,m
接下来n行每行4个整数a[i],b[i],Ci,Di
再接下来m行每行两个整数s,t表示第s支队伍和第t支队伍之间将有一场比赛,注意两只队间可能有多场比赛。
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
2<=n<=5000,0<=m<=1000,0<=di<=ci<=10,0<=a[i],b[i]<=50.
Source
这题很棒棒,肯定是个费用流。我们可以首先假设所有场次都是输的,然后每次调整赢的场次来获得最小答案。
怎么建边呢?
S->比赛 流量为1,费用为0 mean : 一场比赛;
比赛->两只队伍 流量为1,费用为0 mean : 流过去则表示这支队伍获得了胜利;
队伍->T 连若干条边,流量为1,费用为 C*(2a+1)-D*(2b-1) mean : 获胜得到的收益,
为什么呢?这个可以用平方关系得到(多赢一场,少输一场)
然后用原来的答案+最小费用即可。
Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 using namespace std; 9 typedef long long s64; 10 11 const int ONE = 50001; 12 const int EDG = 1000001; 13 const int INF = 2147483640; 14 15 int n,m; 16 int x,y; 17 int S,T; 18 int Num[ONE]; 19 int next[EDG],first[ONE],go[EDG],from[EDG],pas[EDG],w[EDG],tot; 20 int dist[ONE],pre[ONE],vis[ONE]; 21 int tou,wei,q[ONE]; 22 int Ans; 23 24 struct power 25 { 26 int a,b,C,D; 27 }A[ONE]; 28 29 inline int get() 30 { 31 int res=1,Q=1; char c; 32 while( (c=getchar())<48 || c>57) 33 if(c==‘-‘)Q=-1; 34 if(Q) res=c-48; 35 while((c=getchar())>=48 && c<=57) 36 res=res*10+c-48; 37 return res*Q; 38 } 39 40 void Add(int u,int v,int flow,int z) 41 { 42 next[++tot]=first[u]; first[u]=tot; go[tot]=v; from[tot]=u; pas[tot]=flow; w[tot]=z; 43 next[++tot]=first[v]; first[v]=tot; go[tot]=u; from[tot]=v; pas[tot]=0; w[tot]=-z; 44 } 45 46 bool Bfs() 47 { 48 for(int i=S;i<=T;i++) dist[i] = INF; 49 dist[S] = 0; vis[S] = 1; 50 tou = 0; wei = 1; q[1] = S; 51 while(tou < wei) 52 { 53 int u = q[++tou]; 54 for(int e=first[u]; e; e=next[e]) 55 { 56 int v = go[e]; 57 if(dist[v] > dist[u] + w[e] && pas[e]) 58 { 59 dist[v] = dist[u] + w[e]; pre[v] = e; 60 if(!vis[v]) 61 { 62 vis[v] = 1; 63 q[++wei] = v; 64 } 65 } 66 } 67 vis[u] = 0; 68 } 69 return dist[T] != INF; 70 } 71 72 void Deal() 73 { 74 int x = INF; 75 for(int e=pre[T]; e; e=pre[from[e]]) x = min(x,pas[e]); 76 for(int e=pre[T]; e; e=pre[from[e]]) 77 { 78 pas[e] -= x; 79 pas[((e-1)^1)+1] += x; 80 Ans += x*w[e]; 81 } 82 } 83 84 void Build() 85 { 86 S=0; T=n+m+1; 87 for(int i=1;i<=m;i++) 88 { 89 x=get(); y=get(); 90 Add(S,i, 1,0); 91 Add(i,x+m, 1,0); Add(i,y+m, 1,0); 92 93 Num[x]++; Num[y]++; 94 A[x].b++; A[y].b++; 95 } 96 97 for(int i=1;i<=n;i++) 98 { 99 Ans += A[i].a*A[i].a * A[i].C + A[i].b*A[i].b * A[i].D; 100 for(int j=1;j<=Num[i];j++) 101 { 102 Add(i+m,T, 1,A[i].C*(2*A[i].a+1) - A[i].D*(2*A[i].b-1) ); 103 A[i].a++; A[i].b--; 104 } 105 } 106 } 107 108 int main() 109 { 110 n=get(); m=get(); 111 for(int i=1;i<=n;i++) 112 { 113 A[i].a=get(); A[i].b=get(); 114 A[i].C=get(); A[i].D=get(); 115 } 116 117 Build(); 118 119 while(Bfs()) Deal(); 120 121 printf("%d",Ans); 122 123 }
时间: 2024-11-08 07:57:35