900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 【BZOJ 1449】 1449: [JSOI]球队收益 (最小费用流)

【BZOJ 1449】 1449: [JSOI]球队收益 (最小费用流)

时间:2021-05-09 23:48:42

相关推荐

【BZOJ 1449】 1449: [JSOI]球队收益 (最小费用流)

1449: [JSOI]球队收益

Time Limit:5 SecMemory Limit:64 MB

Submit:841Solved:483

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

【题意】

给定n支球队,第i支球队已经赢了win[i]场,输了lose[i]场,接下来还有m场比赛,每个球队最终的收益为Ci∗x[i]^2+Di∗y[i]^2,其中x[i]为最终的胜场,y[i]为最终的负场,求最小化收益。

【分析】

先差分,再拆边。

注意,输赢都有贡献,普通做法不行。直接当成那些比赛所有人都输,那只要计算赢的那个人的贡献。

然后差分:

赢k-1场:c[i]*(win[i]+(k-1))^2+d[i]*(sm[i]+lose[i]-(k-1))^2

赢k场:c[i]=(win[i]+k)^2+d[i]*(sm[i]+lose[i]-k)^2

相减得到赢第k场:c[i]*(2*win[i]-(2*k-1))-d[i]*(2*(lose[i]+sm[i])-(2*k-1))

这是单调的,所以把原本的贡献+最大费用流就好了。

可以膜Po姐:/PoPoQQQ/article/details/46619517

1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 5010 9 #define Maxm 1010 10 #define INF 0xfffffff 11 12 int mymin(int x,int y) {return x<y?x:y;} 13 14 int win[Maxn],lose[Maxn],c[Maxn],d[Maxn],sm[Maxn]; 15 16 struct node 17 { 18int x,y,f,c,o,next; 19 }t[Maxm*100]; 20 int len,first[Maxn*2]; 21 22 void ins(int x,int y,int f,int c) 23 { 24t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c; 25t[len].next=first[x];first[x]=len;t[len].o=len+1; 26t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c; 27t[len].next=first[y];first[y]=len;t[len].o=len-1; 28 } 29 30 queue<int > q; 31 int st,ed; 32 int flow[Maxn*2],pre[Maxn*2],dis[Maxn*2]; 33 bool inq[Maxn*2]; 34 bool bfs() 35 { 36while(!q.empty()) q.pop(); 37// memset(dis,-1,sizeof(dis)); 38for(int i=1;i<=ed;i++) dis[i]=INF; 39memset(inq,0,sizeof(inq)); 40flow[st]=INF;q.push(st);dis[st]=0; 41inq[st]=1; 42while(!q.empty()) 43{ 44 int x=q.front(); 45 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 46 { 47 int y=t[i].y; 48 if(dis[y]>dis[x]+t[i].c) 49 { 50 dis[y]=dis[x]+t[i].c; 51 pre[y]=i; 52 flow[y]=mymin(flow[x],t[i].f); 53 if(!inq[y]) 54 { 55 q.push(y); 56 inq[y]=1; 57 } 58 } 59 } 60 q.pop();inq[x]=0; 61} 62if(dis[ed]==INF) return 0; 63return 1; 64 } 65 66 int sum=0; 67 int max_flow() 68 { 69while(bfs()) 70{ 71 int x=ed; 72 sum+=flow[ed]*dis[ed]; 73 int a=flow[ed]; 74 while(x!=st) 75 { 76 t[pre[x]].f-=a; 77 t[t[pre[x]].o].f+=a; 78 x=t[pre[x]].x; 79 } 80} 81printf("%d\n",sum); 82 } 83 84 void output() 85 { 86for(int i=1;i<=len;i+=2) 87printf("%d -> %d %d %d\n",t[i].x,t[i].y,t[i].f,t[i].c); 88 } 89 90 int main() 91 { 92int n,m; 93scanf("%d%d",&n,&m); 94for(int i=1;i<=n;i++) scanf("%d%d%d%d",&win[i],&lose[i],&c[i],&d[i]); 95st=n+m+1;ed=st+1; 96memset(sm,0,sizeof(sm)); 97for(int i=1;i<=m;i++) 98{ 99 int x,y;100 scanf("%d%d",&x,&y);101 ins(x,n+i,1,0);102 ins(y,n+i,1,0);103 ins(n+i,ed,1,0);104 sm[x]++;sm[y]++;105}106for(int i=1;i<=n;i++)107{108 for(int j=1;j<=sm[i];j++) ins(st,i,1,c[i]*(2*win[i]+2*j-1)-d[i]*(2*(sm[i]+lose[i])-(2*j-1)));109 sum+=c[i]*win[i]*win[i]+d[i]*(lose[i]+sm[i])*(lose[i]+sm[i]);110}111max_flow();112return 0;113 }

View Code

-04-0108:20:09

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。