洛谷

题意:

给出\(n\)个点,\(m\)条边,现在有\(k,k\leq 10\)个人从\(0\)号点出发前往\(n\)点。

规定若某个人想要到达\(x\)点,则\(1\)~\(x-1\)号点都有人到达过才行。

每条边都有对应长度,问某一个人走到\(n\)点时,所有人走的路径长度和最小为多少。

思路:

  • 直接考虑路径较为繁琐,我们可以直接考虑一个人摧毁的点集,发现点集中的点的标号是递增的。
  • 从\(u\)到\(v,u<v\)的路径可能经过\(0\)~\(v-1\)中的任意一点,这里可以直接floyd预处理出来,那么两点之间的路径长度即可确定。
  • 考虑费用流。我们将点拆为\(i,i'\),\(i\)连向\(T\),\(S\)连向\(i'\),\(i'\)连向\(j,j>i\)。容量都为\(1\),费用只有两点之间连边时才产生费用。最后\(S\)连向\(0'\),容量为\(k\),费用为\(0\);
  • 以上建图保证每个点只会被用一次,并且最后最多\(k\)条不重叠的单调递增的路径。
  • 直接跑最小费用流即可。

其实就类似于求\(k\)个上升子序列,用流量来限制每个点只能选一次并且每个点都会选,并且选择两个点会附加费用。

代码如下:

/*
* Author: heyuhhh
* Created Time: 2019/10/31 10:37:25
*/
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define sz(x) (int)(x).size()
#define all(x) (x).begin(), (x).end()
#define INF 0x3f3f3f3f
#ifdef Local
#define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
void err() { std::cout << '\n'; }
template<typename T, typename...Args>
void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
#define dbg(...)
#endif
void pt() {std::cout << '\n'; }
template<typename T, typename...Args>
void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1005, M = 20005; int n, m, k; struct E {
int from, to, cp, v;
E() {}
E(int f, int t, int cp, int v) : from(f), to(t), cp(cp), v(v) {}
}; struct MCMF {
int n, m, s, t;
vector<E> edges;
vector<int> G[N];
bool inq[N];
int d[N], p[N], a[M]; void init(int _n, int _s, int _t) {
n = _n; s = _s; t = _t;
for(int i = 0; i <= n; i++) G[i].clear();
edges.clear(); m = 0;
} void addedge(int from, int to, int cap, int cost) {
edges.emplace_back(from, to, cap, cost);
edges.emplace_back(to, from, 0, -cost);
G[from].push_back(m++);
G[to].push_back(m++);
} bool BellmanFord(int &flow, int &cost) {
for(int i = 0; i <= n; i++) d[i] = INF;
memset(inq, 0, sizeof inq);
d[s] = 0, a[s] = INF, inq[s] = true;
queue<int> Q; Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
inq[u] = false;
for (int& idx: G[u]) {
E &e = edges[idx];
if (e.cp && d[e.to] > d[u] + e.v) {
d[e.to] = d[u] + e.v;
p[e.to] = idx;
a[e.to] = min(a[u], e.cp);
if (!inq[e.to]) {
Q.push(e.to);
inq[e.to] = true;
}
}
}
}
if (d[t] == INF) return false;
flow += a[t];
cost += a[t] * d[t];
int u = t;
while (u != s) {
edges[p[u]].cp -= a[t];
edges[p[u] ^ 1].cp += a[t];
u = edges[p[u]].from;
}
return true;
} int go() {
int flow = 0, cost = 0;
while (BellmanFord(flow, cost));
return cost;
}
} MM; int g[155][155]; void run(){
for(int i = 0; i <= n; i++) {
for(int j = 0; j <= n; j++) {
g[i][j] = INF;
}
}
for(int i = 1; i <= m; i++) {
int u, v, w;
cin >> u >> v >> w;
g[u][v] = g[v][u] = min(g[u][v], w);
}
int S = 2 * n + 2, T = S + 1;
for(int k = 0; k <= n; k++) {
for(int i = 0; i <= n; i++) {
for(int j = 0; j <= n; j++) {
if(k <= max(i, j)) {
g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}
}
}
}
MM.init(T, S, T);
for(int i = 0; i < n; i++) {
for(int j = i + 1; j <= n; j++) {
if(g[i][j] != INF) {
MM.addedge(i + n + 1, j, 1, g[i][j]);
}
}
}
for(int i = 1; i <= n; i++) {
MM.addedge(S, i + n + 1, 1, 0);
MM.addedge(i, T, 1, 0);
}
MM.addedge(S, 0 + n + 1, k, 0);
int ans = MM.go();
cout << ans << '\n';
} int main() {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cout << fixed << setprecision(20);
while(cin >> n >> m >> k) run();
return 0;
}

【洛谷P4542】 [ZJOI2011]营救皮卡丘(费用流)的更多相关文章

  1. bzoj2324 [ZJOI2011]营救皮卡丘 费用流

    [ZJOI2011]营救皮卡丘 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2653  Solved: 1101[Submit][Status][D ...

  2. BZOJ.2324.[ZJOI2011]营救皮卡丘(费用流 Floyd)

    BZOJ 洛谷 首先预处理出\(dis[i][j]\),表示从\(i\)到\(j\)的最短路.可以用\(Floyd\)处理. 注意\(i,j\)是没有大小关系限制的(\(i>j\)的\(dis[ ...

  3. 洛咕P4542 [ZJOI2011]营救皮卡丘

    套路题? 感觉讲不清,先写建图 把每个点拆成两个,A和B, S->Ai流量=1费用=0,Bi->T流量=1费用=0, Ai->Bj流量=1费用=ij最短路 还有一个特殊的s点,S-& ...

  4. 【BZOJ 2324】[ZJOI2011]营救皮卡丘 费用流

    本人实行诱骗拐卖(利用自然分层与实际意义),正解拼接补充(充分利用最大流限制(不浪费任何一个走出去的机会而不是不浪费任何一个已有的流)与问题转换) #include <cstdio> #i ...

  5. P4542 [ZJOI2011]营救皮卡丘(Floyd+网络流)

    P4542 [ZJOI2011]营救皮卡丘 乍一看似乎没啥题相似的 仔细一看,$N<=150$ 边又是双向边,似乎可以用Floyd搞   先跑一遍Floyd处理出$dis[i][j]$ 注意到走 ...

  6. bzoj 2324 ZJOI 营救皮卡丘 费用流

    题的大概意思就是给定一个无向图,边有权值,现在你有k个人在0点,要求走到n点,且满足 1:人们可以分头行动,可以停在某一点不走了 2:当你走到x时,前x-1个点必须全部走过(不同的人走过也行,即分两路 ...

  7. P4542 [ZJOI2011]营救皮卡丘

    题目链接 题意分析 我们仔细分析一下 发现题目要求用最多\(k\)条路径实现最小权覆盖 首先由于最小路径覆盖针对的是有向图 但是这是一个无向图 所以我们面向对象编程 我们维护一个数组\(d[i][j] ...

  8. 【BZOJ2324】[ZJOI2011]营救皮卡丘(网络流,费用流)

    [BZOJ2324][ZJOI2011]营救皮卡丘(网络流,费用流) 题面 BZOJ 洛谷 题解 如果考虑每个人走的路径,就会很麻烦. 转过来考虑每个人破坏的点集,这样子每个人可以得到一个上升的序列. ...

  9. bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)

    2324: [ZJOI2011]营救皮卡丘 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1777  Solved: 712[Submit][Stat ...

  10. BZOJ 2324: [ZJOI2011]营救皮卡丘( floyd + 费用流 )

    昨晚写的题...补发一下题解... 把1~N每个点拆成xi, yi 2个. 预处理i->j经过编号不超过max(i,j)的最短路(floyd) S->0(K, 0), S->xi(1 ...

随机推荐

  1. POJ2976Dropping tests(分数规划)

    传送门 题目大意:n个二元组a[i],b[i],去掉k个,求sigma a[i]/ sigma b[i]的最大值 代码: #include<iostream> #include<cs ...

  2. A1093 Count PAT's (25 分)

    一.技术总结 这是一个逻辑题,题目大职意思是可以组成多少个PAT,可以以A为中心计算两边的P和T,然后数量乘积最后相加便是答案. 还有一个注意的是每次相加后记得mod,取余,不要等到最后加完再取余,会 ...

  3. Paper | Residual Dense Network for Image Super-Resolution

    目录 Residual dense block & network 和DenseNet的不同 摘要和结论 发表在2018年CVPR. 摘要和结论都在强调方法的优势.我们还是先从RDN的结构看起 ...

  4. NORDIC超低功耗蓝牙4.0 NRF51822QFAA和NRF51802QFAA

    51822-QFAA和51802-QFAA在FLASH RAM的容量没有差别, 两者都是出自NORDIC原厂,: 区别在于: 1.接收灵敏度 51802是-91dBm;51822是-93dBm,这个差 ...

  5. JMS简介与入门

    1:JMS引入 如果手机只能进行实时通话,没有留言和短信功能会怎么样?一个电话打过来,正好没有来得及接上,那么这个电话要传递的信息肯定就收不到了.为什么不能先将信息存下来,当用户需要查看信息的时候再去 ...

  6. background属性怎么添加2个或多个背景图

    最近遇到一个需求,下面充值金额按钮是一个背景图,点击之后显示的状态也是一个背景图,如下图      按照惯用的套路,新增一个class,点击后的状态直接写在里面即可 然而点击后,虽然状态背景成功显示出 ...

  7. Java & PHP RSA 互通密钥、签名、验签、加密、解密

    RSA加密算法是一种非对称加密算法.在公开密钥加密和电子商业中RSA被广泛使用.RSA是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Le ...

  8. 云原生生态周报 Vol. 13 | Forrester 发布企业级容器平台报告

    业界要闻 近日,全球知名市场调研机构 Forrester 发布首个企业级公共云容器平台报告.其中,阿里云容器服务的市场表现全球前三.中国第一,同时创造中国企业最好成绩,进入强劲表现者象限.报告显示,阿 ...

  9. 用Python帮你上马,哪里无码打哪里

    目录 0 引言 1 环境 2 需求分析 3 代码实现 4 代码全景展示 5 后记 0 引言 所谓的像素图,就是对图像做一个颗粒化的效果,使其产生一种妙不可言的朦胧感.费话不多说,先来看一张效果图. ▲ ...

  10. 一个JAVA应用启动缓慢问题排查 --来自jdk securerandom 的问候

    开发某个项目过程中,就需求,搭建了一套测试环境.很快完成! 后来代码中加入了许多新功能,会涉及到反复重启,然后就发现了启动特别慢.这给原本功能就不多的应用增添了许多的负担. 我决定改变这一切!找到启动 ...