POJ 2516Minimum Cost(最小费用流+特判)
【题意】:
有N个人,M个仓库,每个人需要物品,个数都等于共同的K,仓库中有对应的K件物品的数量,随后给K个N*M矩阵(小写k, n, m表示K,N,M对应的子集),表明m个仓库到第n个人的位置运送k物品的花费,求
满足所有人的订单要求所需要的花费,如果不能满足所有人则输出-1
【思路】:
我的思路是建立源点sp,汇点tp, 把仓库和人所在的点都进行拆分,对每个仓库拆分成K个点,可以想象成一个大仓库由K个小仓库组成,每个小仓库只发放第k种物品,每个人也分成K个点,每个点接受一种k物品,sp与仓库的拆点进行连边,权重为这个小仓库存放的k物品的数量,花费为0,人的拆点与tp连边,权重为人拆点所需要的k物品的数量,费用为0,最后将仓库的拆点与人的拆点进行连边,权重为inf,费用为矩阵中对应的费用。
【重要】——>解决TLE问题
我的想法可能与网上的题解不同,我看有很多是分别跑k次费用流,最后的费用总和为结果,我在一开始也是疯狂TLE,然后加上特判就过了?
【特判】——>解决TLE
将输入分成三部分与N有关——与M有关——K个N*M矩阵
判定是否有供不应求的情况,将前两部分输入(N*K和N*K)分别存储下来,N*K代表所需要的部分,M*K代表供应的部分,对每个k进行遍历,然后求每个n的和sum1,每个m的和sum2,如果sum1>sum2则不对第三部分输入处理(K个N*M矩阵),待输入结束后不进行费用流算法,直接输出-1即可
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std; const int maxn = 1e4 + ;
const int maxe = 1e6 + ;
const int N = + ;
const int inf = 0x3f3f3f3f;
struct edge{
int to, w, c, next;
} ed[maxe];
int head[maxn], tot, ns;
int n, m, k, ware[N][N], p[N][N];
int sp, tp, d[maxn], pre[maxn], a[maxn];
bool inq[maxn];
inline void init(){
memset( head, -, sizeof(head) ) ;
tot = ;
ns = (n+m)*k+;
sp = ; tp = ns-;
} inline void add( int u, int v, int w, int c ){
ed[++tot].to = v; ed[tot].w = w; ed[tot].c = c; ed[tot].next = head[u]; head[u] = tot;
ed[++tot].to = u; ed[tot].w = ; ed[tot].c = -c; ed[tot].next = head[v]; head[v] = tot;
} inline bool spfa( int &flow, int &cost ){
for( int i=; i<ns; i++ ){
inq[i] = ;
d[i] = inf;
}
queue<int> q;
d[sp] = pre[sp] = ;
a[sp] = inf;
inq[sp] = ;
q.push(sp);
while( q.size() ){
int x = q.front();
q.pop();
inq[x] = ;
for( int i=head[x]; ~i; i=ed[i].next ){
int y = ed[i].to;
if( ed[i].w> && d[y]>d[x]+ed[i].c ){
d[y] = d[x]+ed[i].c;
pre[y] = i;
a[y] = min(a[x], ed[i].w);
if( !inq[y] ){
inq[y] = ;
q.push(y);
}
}
}
}
if( d[tp]==inf ) return ;
flow += a[tp];
cost += a[tp]*d[tp];
for( int x=tp; x!=sp; x=ed[pre[x]^].to ){
ed[pre[x]].w -= a[tp];
ed[pre[x]^].w += a[tp];
}
return ;
} inline void mcmf( int &flow, int &cost ){ while(spfa(flow, cost)); } int main(){
while( ~scanf("%d%d%d", &n, &m, &k), (n||m||k) ){
init();
int num, sum = ;
for( int i=; i<=n; i++ )
for( int j=; j<=k; j++ ){
scanf("%d", &p[i][j]);
sum += p[i][j];
add( (i-)*k+j, tp, p[i][j], );
}
for( int i=; i<=m; i++ )
for( int j=; j<=k; j++ ){
scanf("%d", &ware[i][j]);
add( sp, (i-)*k+j+n*k, ware[i][j], );
}
bool flag = ;
for( int i=; i<=k; i++ ){
int sum1 = , sum2 = ;
for( int j=; j<=n; j++ ) sum1 += p[j][i];
for( int j=; j<=m; j++ ) sum2 += ware[j][i];
if( sum2<sum1 ) {flag = ; break;} //判断是否存在供不应求,如果存在则直接输出-1
}
for( int l=; l<=k; l++ )
for( int i=; i<=n; i++ )
for( int j=; j<=m; j++ ){
int num;
scanf("%d", &num);
if( flag ) continue; //如果出现供不应求则不进行处理,只读取数据即可
add( (j-)*k+l+n*k, (i-)*k+l, inf, num );
}
if( flag ){ puts("-1"); continue; } //输出-1
int flow = , cost = ;
mcmf(flow, cost);
if( flow>=sum ) printf("%d\n", cost);
else puts("-1");
} return ;
}
POJ 2516Minimum Cost(最小费用流+特判)的更多相关文章
- poj 2516Minimum Cost
http://poj.org/problem?id=2516 #include<cstdio> #include<cstring> #include<algorithm& ...
- poj 2049(二分+spfa判负环)
poj 2049(二分+spfa判负环) 给你一堆字符串,若字符串x的后两个字符和y的前两个字符相连,那么x可向y连边.问字符串环的平均最小值是多少.1 ≤ n ≤ 100000,有多组数据. 首先根 ...
- POJ 2516 Minimum Cost 最小费用流
题目: 给出n*kk的矩阵,格子a[i][k]表示第i个客户需要第k种货物a[i][k]单位. 给出m*kk的矩阵,格子b[j][k]表示第j个供应商可以提供第k种货物b[j][k]单位. 再给出k个 ...
- POJ 2516 Minimum Cost 最小费用流 难度:1
Minimum Cost Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 13511 Accepted: 4628 Des ...
- Poj(2195),最小费用流,SPFA
题目链接:http://poj.org/problem?id=2195 Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
- Poj(3259),SPFA,判负环
题目链接:http://poj.org/problem?id=3259 Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submis ...
- poj 2942(点双连通+判奇圈)
题目链接:http://poj.org/problem?id=2942 思路:我们对于那些相互不憎恨的骑士连边,将每次参加会议的所有人(不一定是整个骑士团,只需人数>=3且为奇数)看做一个点双联 ...
- Farm Tour POJ - 2135 (最小费用流)
When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= ...
- Poj 3259 Wormholes(spfa判负环)
Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42366 Accepted: 15560 传送门 Descr ...
随机推荐
- [LeetCode] 465. Optimal Account Balancing 最优账户平衡
A group of friends went on holiday and sometimes lent each other money. For example, Alice paid for ...
- vue-lazyload 图片懒加载
vue-lazyload简单使用 github地址:https://github.com/hilongjw/vue-lazyload 1.安装插件 npm install vue-lazyload - ...
- Salesforce 开发整理(九) 开发中使用的一些小技巧汇总[持续更新]
1.查询一个对象下所有字段 当需要查询一个对象所有字段进行复制或其他操作,可以使用一段拼接的语句来查询 String query = 'select '; for(String fieldApi : ...
- ConcurrentHashMap竟然也有死循环问题?
前几天和朋友闲聊,说遇到了一个ConcurrentHashMap死循环问题,当时心里想这不科学呀?ConcurrentHashMap怎么还有死循环呢,毕竟它已经解决HashMap中rehash中死循环 ...
- PHP中直接使用sql语句
SELECT * FROM `tf_user` WHERE (`company_id` = '117' OR `other_company_ids` LIKE '%117,%' OR `other_c ...
- ArrayList 源码分析 基于jdk1.8:
1:数据结构: transient Object[] elementData; //说明内部维护的数据结构是一个Object[] 数组 成员属性: private static final int ...
- [转帖]Linux date命令的用法(转)
Linux date命令的用法(转) https://www.cnblogs.com/asxe/p/9317811.html 1.命令:date 2.命令功能:date 可以用来显示或设定系统的日期与 ...
- Prometheus 编写告警规则案例
Prometheus 编写告警规则案例 注:确保alertmanager配置完毕! 1.创建编辑文件:vim /usr/local/prometheus/rules/node.yml # groups ...
- Docker File
- 实现外网远程桌面内网的电脑和外网访问内网的FTP
基于之前两篇文章搭建了ngrok实现了内网穿透,用过了http和https的协议完成了外网访问内网的网站,这一篇教大家用tcp协议实现外网远程桌面内网的电脑和外网访问内网的FTP. 一.外网远程桌面 ...