BZOJ 1449: [JSOI2009]球队收益 拆边费用流
来源:互联网 发布:在jsp中写java代码 编辑:程序博客网 时间:2024/06/05 05:24
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
解法:不会,膜拜神牛
题解来自:http://blog.csdn.net/sunshinezff/article/details/51131649 尊重知识产权
直接算支出不好计算。
可以先假设所有队伍一开始都输了.
考虑每个队伍赢一场会增加多少支出.
c*(x+1)^2-d*(y-1)^2-c*x^2-d*y^2=2*c*x-2*d*y+c+d;
所以我们可以从源点向每场比赛连容量为1费用为0的边。
每场比赛向这场比赛的两支队伍连容量为1费用为0的边。
然后统计一下每支队伍参加的比赛数。
每支队伍向汇点连这支队伍的比赛数条边.
容量都为1.费用依次为当前状态再多赢1场增加的支出.
初始答案加上最小费用流即可。
///BZOJ 1449#include <bits/stdc++.h>using namespace std;const int inf = 0x3FFFFFFF;const int maxn = 6500;struct node{ int st, en, flow, cost, next; node(){} node(int st, int en, int flow, int cost, int next):st(st),en(en),flow(flow),cost(cost),next(next){}}E[201000];int num, p[maxn];void init(){ memset(p, -1, sizeof(p)); num = 0;}void add(int st, int en, int flow, int cost){ E[num] = node(st, en, flow, cost, p[st]); p[st] = num++; E[num] = node(en, st, 0, -cost, p[en]); p[en] = num++;}int pre[maxn];int dis[maxn];bool fg[maxn];bool spfa(int st, int en){ for(int i=0;i<=en;i++){ fg[i] = 0, dis[i] = inf, pre[i]=-1; } queue<int>q; q.push(st); fg[st]=1; dis[st]=0; while(!q.empty()){ int u = q.front(); q.pop(); fg[u]=0; for(int i=p[u];~i;i=E[i].next){ int v = E[i].en; if(E[i].flow&&dis[v]>dis[u]+E[i].cost){ dis[v] = dis[u]+E[i].cost; pre[v]=i; if(!fg[v]){ fg[v]=1; q.push(v); } } } } if(dis[en] < inf) return 1; return 0;}int solve(int st, int en){ int ans=0; while(spfa(st,en)){ int d = inf; for(int i=pre[en];i+1;i=pre[E[i].st]) d = min(d, E[i].flow); for(int i=pre[en];i+1;i=pre[E[i].st]){ E[i].flow -= d; E[i^1].flow += d; ans += d*E[i].cost; } } return ans;}int win[maxn], lose[maxn], a[maxn], b[maxn], c[maxn], d[maxn];int n, m, ans=0;int main(){ scanf("%d%d", &n,&m); int source = n+m+1, sink=source+1; for(int i=1; i<=n; i++){ scanf("%d%d%d%d", &win[i], &lose[i], &c[i], &d[i]); } for(int i=1; i<=m; i++){ scanf("%d%d", &a[i],&b[i]); lose[a[i]]++; lose[b[i]]++; } for(int i=1; i<=n; i++) ans += c[i]*win[i]*win[i]+d[i]*lose[i]*lose[i]; init(); for(int i=1; i<=m; i++){ add(source, i, 1, 0); add(i, a[i]+m, 1, 0); add(i, b[i]+m, 1, 0); int tmp = c[a[i]]*(2*win[a[i]]+1)-d[a[i]]*(2*lose[a[i]]-1); add(a[i]+m, sink, 1, tmp); win[a[i]]++; lose[a[i]]--; tmp = c[b[i]]*(2*win[b[i]]+1)-d[b[i]]*(2*lose[b[i]]-1); add(b[i]+m, sink, 1, tmp); win[b[i]]++; lose[b[i]]--; } ans = ans + solve(source, sink); printf("%d\n", ans); return 0;}
0 0
- [拆边费用流] BZOJ 1449 [JSOI2009]球队收益
- BZOJ 1449: [JSOI2009]球队收益 拆边费用流
- BZOJ 1449 JSOI2009 球队收益 费用流
- bzoj 1449: [JSOI2009]球队收益 (费用流)
- bzoj 1449 [JSOI2009]球队收益(费用拆分,最小费用流)
- 【bzoj1449/2895】 JSOI2009球队收益 费用流
- 【bzoj1449】【JSOI2009】【球队收益】【费用流】
- BZOJ 1449/2895: [JSOI2009]球队收益|网络流
- 1449: [JSOI2009]球队收益
- BZOJ 1449: [JSOI2009]球队收益 此坑必填 先去打cf
- bzoj1449【JSOI2009】球队收益
- 【JSOI2009】bzoj1449 球队收益
- bzoj1449: [JSOI2009]球队收益
- [JSOI2009]球队收益
- BZOJ1449: [JSOI2009]球队收益
- 【BZOJ1449】[JSOI2009]球队收益【最小费用最大流】【单调增函数建图】
- bzoj1149/2895 [JSOI2009]球队收益
- bzoj1449/2895[JSOI2009]球队收益
- DescendingOrder
- Axure使用——创建折叠菜单
- HTML5 拖放Drag 和 drop用法以及事件介绍
- First Unique Character in a String
- eclipse,工程/文件目录,相对路径(真心的详细~)
- BZOJ 1449: [JSOI2009]球队收益 拆边费用流
- 【算法题】不使用加减乘除符号计算两数之和a+b
- SharedPreference的使用 第一次进入APP时,进入导航页面,再次进入时直接进入主页面 去除ActionBar
- POJ
- 文本处理工具
- Nginx 源码阅读笔记8 epoll 模块
- 软件测试1
- 561. Array Partition I
- PAT1044 火星数字