POJ 3686 *最小费用流-转化成普通指派问题)
题意】
有N个订单和M个机器,给出第i个订单在第j个机器完成的时间Mij,每台机器同一时刻只能处理一个订单,机器必须完整地完成一个订单后才能接着完成下一个订单。问N个订单完成时间的平均值最少为多少。
分析 :
最小费用最大流
如果每个工厂只能完成一个订单的话,那就是指派问题了。跑一遍最小费用流即可。但是题目每个工厂可能完成多个。
所以需要将其拆点使得每个工厂只能完成一个订单,进而转换成指派问题。对一个工厂来说,如果每个订单都在这个
工厂完成的话,那么时间为T=t1 + (t1+t2) + (t1+t2+t3) +... = n*t1 + (n-1)*t2 + (n-2)*t3 + ...就可将其看成
是n个只能完成一个订单的工厂只不过它们需要乘于花费的1到N倍。
#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring> using namespace std;
const int maxn = ;
const int INF = 0x3f3f3f3f; typedef pair<int,int> P;
struct Edge
{
int to, cap, cost, rev;
Edge(int to_, int cap_, int cost_, int rev_):to(to_),cap(cap_),cost(cost_),rev(rev_){}
}; vector<Edge> G[maxn];
int V, n, m, relation[][];
int h[maxn], dist[maxn], prevv[maxn], preve[maxn]; void add_edge(int from, int to, int cap, int cost)
{
G[from].push_back(Edge(to, cap, cost, G[to].size()));
G[to].push_back(Edge(from, , -cost, G[from].size()-));
} int min_cost_flow(int s, int t, int f)
{
int res = ;
memset(h, , sizeof(h));
while(f > ) {
priority_queue<P, vector<P>, greater<P> > pq;
fill(dist, dist + V, INF);
dist[s] = ;
pq.push(P(, s));
while(!pq.empty()) {
P p = pq.top(); pq.pop();
int v = p.second;
if(dist[v] < p.first) continue;
for(int i = ; i < G[v].size(); i++) {
Edge& e = G[v][i];
if(e.cap > && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
prevv[e.to] = v;
preve[e.to] = i;
pq.push(P(dist[e.to], e.to));
}
}
}
if(dist[t] == INF) return -; for(int v = ; v < V; v++) h[v] += dist[v]; int d = f;
for(int v = t; v != s; v = prevv[v]) {
d = min(d, G[prevv[v]][preve[v]].cap);
}
f -= d;
res += d * h[t];
for(int v = t; v != s; v = prevv[v]) {
Edge& e = G[prevv[v]][preve[v]];
e.cap -= d;
G[v][e.rev].cap += d;
}
}
return res;
} int main()
{
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T); getchar();
while(T--) {
scanf("%d%d", &n, &m);
for(int i = ; i < maxn; i++) G[i].clear(); for(int i = ; i < n; i++) {
for(int j = ; j < m; j++) {
scanf("%d", &relation[i][j]);
}
} int s = n + n * m, t = s + ;
for(int j = ; j < m; j++) {//工厂
for(int k = ; k < n; k++) {//将工厂拆成n个点
add_edge(n + j * n + k, t, , );
for(int i = ; i < n; i++) {
add_edge(i, n + j * n + k, , (k + ) * relation[i][j]);
}
}
}
for(int i = ; i < n; i++) add_edge(s, i, , );
V = t + ;
printf("%.6f\n", (double)min_cost_flow(s, t, n) / n);
}
return ;
}
POJ 3686 *最小费用流-转化成普通指派问题)的更多相关文章
- B - Housewife Wind POJ - 2763 树剖+边权转化成点权
B - Housewife Wind POJ - 2763 因为树剖+线段树只能解决点权问题,所以这种题目给了边权的一般要转化成点权. 知道这个以后这个题目就很简单了. 怎么转化呢,就把这个边权转化为 ...
- S - Making the Grade POJ - 3666 结论 将严格递减转化成非严格的
S - Making the Grade POJ - 3666 这个题目要求把一个给定的序列变成递增或者递减序列的最小代价. 这个是一个dp,对于这个dp的定义我觉得不是很好想,如果第一次碰到的话. ...
- POJ 1060 Modular multiplication of polynomials(多项式的加减乘除,除法转化成减法来求)
题意:给出f(x),g(x),h(x)的 (最高次幂+1)的值,以及它们的各项系数,求f(x)*g(x)/h(x)的余数. 这里多项式的系数只有1或0,因为题目要求:这里多项式的加减法是将系数相加/减 ...
- BNU 28887——A Simple Tree Problem——————【将多子树转化成线段树+区间更新】
A Simple Tree Problem Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on ZJU. O ...
- 多重背包转化成完全背包 E - Charlie's Change
http://poj.org/problem?id=1787 这个题目我一看就觉得是一个多重背包,但是呢,我不知道怎么输出路径,所以无可奈何,我就只能看一下题解了. 看了题解发现居然是把多重背包转化成 ...
- [LeetCode] Integer to Roman 整数转化成罗马数字
Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 t ...
- HTML5将图片转化成字符画
HTML5将图片转化成字符画 字符画大家一定非常熟悉了,那么如何把一张现有的图片转成字符画呢?HTML5让这个可能变成了现实,通过canvas,可以很轻松实现这个功能.其实原理很简单:扫描图片相应位置 ...
- xml格式的数据转化成数组
将得到的xml格式的数据转化成数组 <?php //构造xml $url = "http://api.map.baidu.com/telematics/v3/weather?locat ...
- yii2得到的数据对象转化成数组
yii2得到的数据对象转化成数组需要用到asArray().1.Customer::find(['id' => $id])->asArray()->one();2.$model = ...
随机推荐
- 0016_练习题d2
__author__ = 'qq593' #!/usr/bin/env python #-*- coding:utf-8 -*- #元素分类,有如下值集合[11,22,33,44,55,66,77,8 ...
- js中FOR循环的陷阱
//闭包解决 循环输出的问题 for(var i=0;i<rows.length;i++) {( function (i) { })(i);
- day17-jdbc 7.Statement介绍
SQL语句:DML.DQL.DCL.DDL.DML和DQL是用的最多的.DCL和DDL用的很少. 程序员一般是操作记录,创建一表很少. package cn.itcast.jdbc; import c ...
- hdu6357 Hills And Valleys
传送门 题目大意 给定一个序列A,求翻转A中一个区间之后的最长不降子序列的长度即翻转的区间 分析 发现直接枚举翻转的区间的话是无论如何都不行的,于是有一个非常神奇的做法.我们再设一个序列B = {0, ...
- cakephp目录结构
- Django models模型ORM
一.ORM介绍 映射关系: 表名 -------------------->类名 字段-------------------->属性 表记录----------------->类实例 ...
- Excel课程学习第二课单元格格式设置
今天要讲的是单元格格式的设置,字体字号的设置,边框设置,合并单元格之类的. 下面看看具体的内容: 1.使用单元格格式工具美化表格 1.1设置单元格格式的对话框在哪里? 下图中三个小箭头都能打开设置单元 ...
- java全栈day09----继承 抽象类
01继承的概述 在Java中,类的继承是指在一个现有类的基础上去构建一个新的类, 构建出来的新类被称作子类,现有类被称作父类在java中 继承如何来实用呢?举个例子 继承的定义格式和使用 *A:继承的 ...
- iTween插件使用
itween插件 itween是一个动画库,作者创建它的目的就是最小的投入实现最大的产出.用它可以轻松实现各种动画,晃动,旋转,移动.褪色.上色.控制音频等. iTween原理: itween的核心是 ...
- .net core 基于NPOI 的excel导入导出类,支持自定义导出哪些字段,和判断导入是否有失败的记录
#region 从Excel导入 //用法 //var cellHeader = new Dictionary<string, string>(); //cellHeader.Add(&q ...