poj - 3686 The Windy's (KM算法)
题意:n个订单和m个生产车间,每个订单在不同的车间生产所需要的时间不一样,并且每个订单只能在同一个车间中完成,直到这个车间完成这个订单就可以生产下一个订单.现在需要求完成n个订单的平均时间最少是多少.(每个订单的单独时间之和/n,包括等待时间)。
主要是建图,考虑第i个订单在第j个车间倒数第k个被生产,那么第i个订单在第j个区间所花费的时间为k*mat[i][j].
每个区间最多生产n个订单,那么就可以把n*m的图转化成n*(n*m)的图进而用km算法求最小权值。
所以把每个权值取反进而求最大权匹配,但是为什么不能直接求最小权匹配还是没想清楚.
注意G++用%f输出,否则wa.
参考:http://www.tuicool.com/articles/jmYNryf
#include<iostream>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int nMax = ;
const int mMax = ;
const int inf = ; int n, m; // n为X集合顶点数量,m为Y集合顶点数量。(1~n和1~m)
int map[nMax][mMax]; // map[i][j]:记录X集合中的i到Y集合中的j所需的费用。
int lx[nMax], ly[mMax];
int link[mMax];
bool x[nMax], y[mMax]; bool dfs(int u){ // 判断能否找到最大完全匹配。
x[u] = true;
for(int v = ; v <= m; v ++)
if(!y[v] && lx[u] + ly[v] == map[u][v]){
y[v] = true;
if(!link[v] || dfs(link[v])){
link[v] = u;
return true;
}
}
return false;
} int KM(){ // KM算法。
int i, j, k, mi;
for(i = ; i <= n; i ++)
for(lx[i] = -inf, j = ; j <= m; j ++)
lx[i] = max(lx[i], map[i][j]);
memset(ly, , sizeof(ly));
memset(link, , sizeof(link));
for(k = ; k <= n; k ++){
while(){
memset(x, , sizeof(x));
memset(y, , sizeof(y));
if(dfs(k)) break;
mi = inf;
for(i = ; i <= n; i ++)
if(x[i])
for(j = ; j <= m; j ++)
if(!y[j])
mi = min(mi, lx[i] + ly[j] - map[i][j]);
for(i = ; i <= n; i ++) if(x[i]) lx[i] -= mi;
for(i = ; i <= m; i ++) if(y[i]) ly[i] += mi;
}
}
int ans = ;
for(i = ; i <= m; i ++)
if(link[i] > )
ans += map[link[i]][i];
return ans;
} int main(){
int t, N, M, i, j, k, mat[nMax][nMax];
scanf("%d", &t);
while(t --){
scanf("%d%d", &N, &M);
for(i = ; i <= N; i ++)
for(j = ; j <= M; j ++)
scanf("%d", &mat[i][j]);
n = N, m = N * M;
for(i = ; i <= N; i ++) // KM算法是求最大权,故这里存负数,最后取反求最小权。
for(j = ; j <= N; j ++)
for(k = ; k <= M; k ++){
map[i][(k-)*N+j] = -j*mat[i][k];
//cout << i << ' ' << (k-1)*N+j << ' ' << j*mat[i][k] << endl;
}
double ans = 1.0*(-KM())/N; // 精度必须取double才AC。
printf("%.6f\n", ans);
}
return ;
}
这题还可以用费用流来解决.不过效率没有KM高.
初始源点和每个订单相连,每个车间拆成n*m个车间,然后和汇点相连.然后和km考虑的一样在订单和车间之间连边.
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = ;
const int INF = 1e9;
struct edge{
int to,next;
int cap,flow,cost;
}e[maxn*maxn];
int n,m;
int head[maxn],sz,res;
bool inq[maxn];
int p[maxn],d[maxn],a[maxn];
void addedge(int u,int v,int cap,int cost){
e[sz].to = v;e[sz].next = head[u];
e[sz].cap = cap;e[sz].flow = ;e[sz].cost = cost;
head[u] = sz ++;
e[sz].to = u;e[sz].next = head[v];
e[sz].cap = ;e[sz].flow = ;e[sz].cost = -cost;
head[v] = sz ++;
}
void init(){
memset(head,-,sizeof(head));
sz = ;
}
queue<int> Q;
int SPFA(int s,int t){
memset(inq,,sizeof(inq));
for(int i = ; i <= t ; i ++) d[i] = INF;
inq[s] = ;d[s] = ;p[s] = -;
a[s] = INF;
Q.push(s);
while(!Q.empty()){
int u = Q.front();Q.pop();
inq[u] = ;
for(int i = head[u] ; i != - ; i = e[i].next){
int v = e[i].to;
if(e[i].cap - e[i].flow > && e[i].cost + d[u] < d[v]){
d[v] = d[u] + e[i].cost;
a[v] = min(e[i].cap - e[i].flow,a[u]);
p[v] = i;
if(!inq[v]){
inq[v] = ;
Q.push(v);
}
}
}
}
int u = t;
if(d[t] == INF) return ;
res += d[t] * a[t];
while(u != s){
e[ p[u] ].flow += a[t];
e[ p[u] ^ ].flow -= a[t];
u = e[ p[u] ^ ].to;
}
return ;
} void MCMF(int s,int t){
res = ;
while(SPFA(s,t));
printf("%.6f\n",res*1.0/n);
} void solve(){
init();
int s,t,mat[][];
scanf("%d%d",&n,&m);
s = ;t = n * m + n + ;
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
scanf("%d",&mat[i][j]);
for(int i = ; i <= n; i ++)
{
addedge(s,i,,);
for(int j = ; j <= n; j ++)
{
for(int k = ; k <= m; k ++)
{
addedge(i,n+(k-)*n+j,,j*mat[i][k]);
}
}
}
for(int i=n+;i<=n*m+n;i++)
addedge(i,t,,);
MCMF(s,t);
}
int main()
{
//freopen("a.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--) solve();
return ;
}
poj - 3686 The Windy's (KM算法)的更多相关文章
- [ACM] POJ 3686 The Windy's (二分图最小权匹配,KM算法,特殊建图)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 4158 Accepted: 1777 Descr ...
- POJ 3686 The Windy's(思维+费用流好题)
The Windy's Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 5362 Accepted: 2249 Descr ...
- poj 3565 uva 1411 Ants KM算法求最小权
由于涉及到实数,一定,一定不能直接等于,一定,一定加一个误差<0.00001,坑死了…… 有两种事物,不难想到用二分图.这里涉及到一个有趣的问题,这个二分图的完美匹配的最小权值和就是答案.为啥呢 ...
- poj 3686 The Windy's
http://poj.org/problem?id=3686 #include <cstdio> #include <cstring> #include <algorit ...
- POJ 2195 Going Home(KM算法模板)
题目链接:http://poj.org/problem?id=2195 题目大意: 给定一个N*M的地图,地图上有若干个man和house,且man与house的数量一致. man每移动一格需花费$1 ...
- POJ 3686 The Windy's (费用流)
[题目链接] http://poj.org/problem?id=3686 [题目大意] 每个工厂对于每种玩具的加工时间都是不同的, 并且在加工完一种玩具之后才能加工另一种,现在求加工完每种玩具的平均 ...
- POJ-3686 The Windy's KM算法 拆点题
参考:https://blog.csdn.net/sr_19930829/article/details/40680053 题意: 有n个订单,m个工厂,第i个订单在第j个工厂生产的时间为t[i][j ...
- POJ 3686 The Windy's 最小费用最大流
每个工厂拆成N个工厂,费用分别为1~N倍原费用. //#pragma comment(linker, "/STACK:1024000000,1024000000") #includ ...
- POJ 3686 The Windy's (最小费用流或最佳完全匹配)
题意:有n个订单m个车间,每个车间均可以单独完成任何一个订单.每个车间完成不同订单的时间是不同的.不会出现两个车间完成同一个订单的情况.给出每个订单在某个车间完成所用的时间.问订单完成的平均时间是多少 ...
随机推荐
- Android Learning Note -- AsyncTask浅尝
AsyncTask 实现原理 AsyncTask是Android提供的轻量级异步类,可以直接继承AsyncTask在类中实现异步操作,并提供接口反馈当前的异步执行程度(通过接口实现UI进度更新),最后 ...
- jstat查看JVM的GC情况
jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上 ...
- 洛谷 P2788 数学1(math1)- 加减算式
题目背景 蒟蒻HansBug在数学考场上,挠了无数次的头,可脑子里还是一片空白. 题目描述 好不容易啊,HansBug终于熬到了做到数学最后一题的时刻了,眼前是一堆杂乱的加减算式.显然成功就在眼前了. ...
- Charles Petzold 编程界大师,世界顶级技术作家 《CODE》值得阅读
<CODE>The Hidden Language of Computer Hardware and Software 从书内容的第一页开始就惊叹于作者的耐心和责任心 整本书以两个隔街对窗 ...
- 原创Couldn't read packet: Connection reset by peer 错误排查思路(推荐)
作为一个运维 不是你懂多少知识才是你的价值 你有幸能遇到多少错误才是你的最大的价值 知识 你有我有大家有 错误我有你没有 这便是我的价值 我遇到一个错误 蛮难遇到的一个错误 所以想分享给大家 下面我 ...
- Docker 启动时报错:iptables:No chain/target/match by the name
重新启动docker后,就好了. service docker restart
- java 随机数 <%=System.currentTimeMillis() %>
java 随机数<c:set var="version" value="<%=System.currentTimeMillis() %>"/& ...
- ProxyFactory
Spring定义了org.springframework.aop.framework.AopProxy接口,并提供了两个final类型的实现类. AopProxy类结构:
- hdu5126 stars
题目描述 题解: 和二维的比起来差不多. 但是这是四维偏序. 所以搞一下CDQ套CDQ. CDQ是维度a已经有序,按维度b排序,然后将维度c存入一维数据结构. 所以我们在第一层CDQ中分治处理,将合法 ...
- python-列表数据类型内置方法
1 列表数据类型(必考) 1.1 用途:兴趣爱好,多个女朋友 1.2 定义方式:[]内用逗号隔开多个元素,多个元素可以是任意数据类型 fangping_boy_friend_list=['ruixin ...