HDU 3667 — Transportation 费用流
2015-06-04 21:11
239 查看
原题:http://acm.hdu.edu.cn/showproblem.php?pid=3667
题意:
有n个点,m条有向边,需要运送k个物品;
下面m行,u v a c,表示从 u 到 v 的路最大容量为c,危险系数为a;
当你在危险系数为a的路上运送x个物品时,费用为a*x*x;
问最小费用,若不能运输k个物品,则输出-1;
思路:
费用流的模板中流量和费用呈线性关系,即a*x;
所以我们要将a*x*x变形;
在平方中,1*1 = 1,2*2 = 1+3, 3*3 = 1+3+5……
所以,对于同一条路来说,第i次走过这条的费用为(2*i+1)*a;注:0<=i<c;
我们对边进行拆边,将流量为c的边,拆成c条流量为1的边;
譬如,在某一条路上运输3个物品,因为我们把每一条路进行了拆分,所以3个物品就是要走三次,第一次费用为a,第二次为3a,第三次为5a,一共的费用就是9a;
题意:
有n个点,m条有向边,需要运送k个物品;
下面m行,u v a c,表示从 u 到 v 的路最大容量为c,危险系数为a;
当你在危险系数为a的路上运送x个物品时,费用为a*x*x;
问最小费用,若不能运输k个物品,则输出-1;
思路:
费用流的模板中流量和费用呈线性关系,即a*x;
所以我们要将a*x*x变形;
在平方中,1*1 = 1,2*2 = 1+3, 3*3 = 1+3+5……
所以,对于同一条路来说,第i次走过这条的费用为(2*i+1)*a;注:0<=i<c;
我们对边进行拆边,将流量为c的边,拆成c条流量为1的边;
譬如,在某一条路上运输3个物品,因为我们把每一条路进行了拆分,所以3个物品就是要走三次,第一次费用为a,第二次为3a,第三次为5a,一共的费用就是9a;
#include<iostream> #include<stdio.h> #include<string.h> #include<queue> #include<math.h> using namespace std; #define ll int #define inf 0x3f3f3f3f #define Inf 0x3FFFFFFFFFFFFFFFLL #define N 605*605*2 #define M 605*605*4 int n, m, k; struct Edge { ll to, cap, cost, nex; Edge(){} Edge(ll to,ll cap,ll cost,ll next):to(to),cap(cap),cost(cost),nex(next){} } edge[M<<1]; ll head , edgenum; ll D , A , P ; bool inq ; void add(ll from,ll to,ll cap,ll cost) { edge[edgenum] = Edge(to,cap,cost,head[from]); head[from] = edgenum++; edge[edgenum] = Edge(from,0,-cost,head[to]); head[to] = edgenum++; } bool spfa(ll s, ll t, ll &flow, ll &cost) { for(ll i = 0; i <= t; i++) D[i] = inf; memset(inq, 0, sizeof inq); queue<ll>q; q.push(s); D[s] = 0; A[s] = inf; while(!q.empty()) { ll u = q.front(); q.pop(); inq[u] = 0; for(ll i = head[u]; ~i; i = edge[i].nex) { Edge &e = edge[i]; if(e.cap && D[e.to] > D[u] + e.cost) { D[e.to] = D[u] + e.cost; P[e.to] = i; A[e.to] = min(A[u], e.cap); if(!inq[e.to]) {inq[e.to]=1; q.push(e.to);} } } } if(D[t] == inf) return false; cost += D[t] * A[t]; flow += A[t]; ll u = t; while(u != s) { edge[ P[u] ].cap -= A[t]; edge[P[u]^1].cap += A[t]; u = edge[P[u]^1].to; } return true; } void Mincost(ll s,ll t) { ll flow = 0, cost = 0; while(spfa(s, t, flow, cost)); if(flow == k) printf("%d\n", cost); else printf("-1\n"); } void init() { memset(head,-1,sizeof head); edgenum = 0; } int main() { while(scanf("%d%d%d", &n, &m, &k)!=EOF) { init(); while(m--) { int u, v, a, c; scanf("%d%d%d%d", &u, &v, &a, &c); for(int i = 0;i<c;i++) add(u, v, 1, (2*i+1)*a); } int s = 0, t = n; add(s, 1, k, 0); Mincost(s, t); } return 0; }
相关文章推荐
- MyBatis多对多增删改查(不建关联实体)
- [android] OpenGL与OpenGL ES简介
- 乂文®便携触摸屏
- 数字在排序数组中出现的次数
- 基于 Android NDK 的学习之旅----- C调用Java
- Linux常用命令
- easy_install 错误Setup script exited with error: Unable to find vcvarsall.bat解决方法
- 动态规划的Warshall和Floyd算法:
- 成员变量,局部变量,实例变量,类变量的区别
- linux配置ip地址(centos7 64bit)
- hdu1232&& hdu1213(简单并查集)
- discuz X3.2 在用户信息表加一个头像字段(已解决)
- iOS百度推送
- STL --> queue单向队列
- hdu1232&& hdu1213(简单并查集)
- Android Service完全解析,关于服务你所需知道的一切(上)
- Android必备的Java知识点
- 深复制和浅复制(clone)
- css三个边距对比
- MySQL 最基本的SQL语法/语句