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 ...
随机推荐
- 【转】用C语言实现FFT算法
傅里叶变换 快速傅里叶变换(Fast Fourier Transform,FFT)是一种可在 时间内完成的离散傅里叶变换(Discrete Fourier transform,DFT)算法. 在算法 ...
- 【CF1097F】Alex and a TV Show
[CF1097F]Alex and a TV Show 题面 洛谷 题解 我们对于某个集合中的每个\(i\),令\(f(i)\)表示\(i\)作为约数出现次数的奇偶性. 因为只要因为奇偶性只有\(0, ...
- 【递归】执行过程探究(c)
c语言 递归的执行过程探究 引用<c primer plus>第五版 9.3.1 递归的使用 /* recur.c -- recursion illustration */ #includ ...
- 学习《Linux网络安全技术与实现》,正文为1、2章的笔记,后面的等待更新
博客地址:http://www.cnblogs.com/zengjianrong/p/3280276.html
- OCC与MVCC 的区别
一.前言 在数据库中,并发控制是指在多个用户/进程/线程同时对数据库进行操作时,如何保证事务的一致性和隔离性的,同时最大程度地并发. 当多个用户/进程/线程同时对数据库进行操作时,会出现3种冲突情形: ...
- Elasticsearch Field Options Norms
Elasticsearch 定义字段时Norms选项的作用 本文介绍ElasticSearch中2种字段(text 和 keyword)的Norms参数作用. 创建ES索引时,一般指定2种配置信息:s ...
- 快速学会使用Vuex
一.Vuex简介 官方定义 Vuex是一个专门为Vue.js应用程序开的状态管理模式 它采用集中式存储管理应用的所有组件的状态 并以相应的规则保证以一种可预测的方式发生变化 二.应用场景 多个视图依赖 ...
- UnicodeDecodeError: 'utf-8' codec can't decode byte 0xa1 in position 3: invalid start byte错误解决办法
这类错误的原因是编码造成的,通常情况下都是utf-8编码,这需要变换一下,改成encoding="ISO-8859-1"即可: file = pd.read_csv("/ ...
- Java基础笔记之String相关知识
(二)String Sring 被声明为 final ,因此不可被继承. String的不可变性: 看String的定义(java9版本): public final class String imp ...
- .NET CORE 控制台应用程序配置log4net日志文件
使用文件格式记录日志 1.新建一个.NET CORE控制台应用程序,添加log4net.dll引用,打开工具->NuGet包管理器->管理解决方案的NuGet程序包. 2.在NuGet-解 ...