P5304 [GXOI/GZOI2019]旅行者
这里是官方题解
一个图 \(n\) 点 \(m\) 条边,里面有 \(k\) 个特殊点,问这 \(k\) 个点之间两两最短路的最小值是多少?
\(n \leq 10^5, m \leq 5 * 10 ^5\)
假设我们把特殊点分成 \(A,B\) 两个集合,新建 \(s\) 连 \(A\) 集合的所有点,边权 \(0\) ,新建 \(t\) 连接 \(B\) 集合里的所有点,边权 \(0\) ,那么 \(s\) 到 \(t\) 的最短路就是 \(A,B\) 集合点之间的最短路的最小值。
那么对于 \(k\) 个特殊点,我们枚举二进制里的第 \(i\) 位,把二进制第 \(i\) 位是 \(0\) 的点放在 \(A\) , \(1\) 的点放在 \(B\) ,用以上方法跑一个最短路。
然后跑 \(log\ n\) 次最短路之后,所有最短路的最小值就是最终答案。
原理是,假设 \(k\) 个特殊点里最近的是 \(x\) 和 \(y\) ,那么 \(x\) 和 \(y\) 一定有一个二进制位不一样,那么他们肯定在那次分组的时候被放进了不同的集合,从而肯定被算进了最后的答案之中最短路。
#include <bits/stdc++.h>
const int MAXN = 100010, MAXM = 700010;
struct Edge {
int y, z;
Edge *next;
}*a[MAXN], POOL[MAXM], *ptr, *back[MAXN];
void AddEdge(int x, int y, int z) {
Edge *tmp = ptr++;
tmp->y = y;
tmp->z = z;
tmp->next = a[x];
a[x] = tmp;
}
int n, nodes[MAXN], k, s, t;
long long dis[MAXN];
long long dijkstra() {
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
std::priority_queue<std::pair<long long, int> > Q;
Q.push(std::make_pair(0, s));
for (int i = 1; i < n + 2; i++) {
while (!Q.empty() && dis[Q.top().second] != -Q.top().first) Q.pop();
if (Q.empty()) break;
int now = Q.top().second;
Q.pop();
for (Edge *p = a[now]; p; p = p->next)
if (dis[p->y] > dis[now] + p->z)
Q.push(std::make_pair(-(dis[p->y] = dis[now] + p->z), p->y));
}
return dis[t];
}
int main(int argc, char* argv[]) {
int T;
scanf("%d", &T);
while (T--) {
ptr = POOL;
memset(a, 0, sizeof a);
int m;
scanf("%d%d%d", &n, &m, &k);
while (m--) {
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
AddEdge(x, y, z);
}
for (int i = 1; i <= k; i++) scanf("%d", nodes + i);
long long Ans = ~0ull>>1;
s = n + 1, t = n + 2;
for (int i = 0; (1 << i) <= k; i++) {
Edge *backup = ptr;
memcpy(back, a, (sizeof a[0]) * (n + 3));
for (int j = 1; j <= k; j++) if (j & (1 << i)) {
AddEdge(s, nodes[j], 0);
} else {
AddEdge(nodes[j], t, 0);
}
Ans = std::min(Ans, dijkstra());
ptr = backup;
memcpy(a, back, (sizeof a[0]) * (n + 3));
for (int j = 1; j <= k; j++) if (j & (1 << i)) {
AddEdge(nodes[j], t, 0);
} else {
AddEdge(s, nodes[j], 0);
}
Ans = std::min(Ans, dijkstra());
ptr = backup;
memcpy(a, back, (sizeof a[0]) * (n + 3));
}
printf("%lld\n", Ans);
}
return 0;
}
P5304 [GXOI/GZOI2019]旅行者的更多相关文章
- 洛谷 P5304 [GXOI/GZOI2019]旅行者(最短路)
洛谷:传送门 bzoj:传送门 参考资料: [1]:https://xht37.blog.luogu.org/p5304-gxoigzoi2019-lv-xing-zhe [2]:http://www ...
- luogu P5304 [GXOI/GZOI2019]旅行者
传送门 所以这个\(5s\)是SMG 暴力是枚举每一个点跑最短路,然后有一个很拿衣服幼稚的想法,就是把所有给出的关键点当出发点,都丢到队列里,求最短路的时候如果当前点\(x\)某个相邻的点\(y\)是 ...
- P5304 [GXOI/GZOI2019]旅行者(最短路/乱搞)
luogu bzoj Orz自己想出神仙正解的sxy 描述略 直接把所有起点推进去跑dijkstra... 并且染色,就是记录到这个点的最短路是由哪个起点引导出来的 然后再把所有边反指跑一次... 之 ...
- 【题解】Luogu P5304 [GXOI/GZOI2019]旅行者
原题传送门 题意:给你k个点,让你求两两最短路之间的最小值 我们考虑二进制拆分,使得每两个点都有机会分在不同的组\((A:0,B:1)\)中,从源点\(S\)向\(A/B\)中的点连边权为0的边,从\ ...
- [洛谷P5304][GXOI/GZOI2019]旅行者
题目大意: 有一张 \(n(n\leqslant10^5)\) 个点 \(m(m\leqslant5\times10^5)\) 条边的有向有正权图,有$k(2\leqslant k\leqslant ...
- [LOJ3087][GXOI/GZOI2019]旅行者——堆优化dijkstra
题目链接: [GXOI/GZOI2019]旅行者 我们考虑每条边的贡献,对每个点求出能到达它的最近的感兴趣的城市(设为$f[i]$,最短距离设为$a[i]$)和它能到达的离它最近的感兴趣的城市(设为$ ...
- 【BZOJ5506】[GXOI/GZOI2019]旅行者(最短路)
[BZOJ5506][GXOI/GZOI2019]旅行者(最短路) 题面 BZOJ 洛谷 题解 正着做一遍\(dij\)求出最短路径以及从谁转移过来的,反过来做一遍,如果两个点不由同一个点转移过来就更 ...
- 洛谷 P 5 3 0 4 [GXOI/GZOI2019]旅行者
题目描述 J 国有 n 座城市,这些城市之间通过 m 条单向道路相连,已知每条道路的长度. 一次,居住在 J 国的 Rainbow 邀请 Vani 来作客.不过,作为一名资深的旅行者,Vani 只对 ...
- BZOJ5506 GXOI/GZOI2019旅行者(最短路)
本以为是个二进制分组傻逼题https://www.cnblogs.com/Gloid/p/9545753.html,实际上有神仙的一个log做法https://www.cnblogs.com/asul ...
随机推荐
- 分享收集的WebGL 3D学习资源
大家好,我在本文中分享了我收集的WebGL 3D相关的博客.书籍.教程.demo等内容,希望对大家学习WebGL和3D有所帮助,谢谢- 相关博客 Wonder技术 Wonder是我们的产品,包含Web ...
- Python--day09(内存管理、垃圾回收机制)
昨天内容回顾 1. 操作文件的三个步骤: 1. 打开文件:硬盘的空间被操作系统持有,文件对象被用用程序持续 2. 操作文件:读写操作 3. 释放文件:释放操作系统对硬盘空间的持有 2. 基础 ...
- sqlalchemy 外键
建表 from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() from sqlalchemy ...
- SQL 之 字符区别(转)
1.CHAR.CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间,不足的自动用空格填充,所以在读取的 ...
- 暂时禁止Cnario Player开机自动启动的办法
如果暂时不需要播放器开机后启动Cnario Player, 有两种办法 从Windows启动菜单禁用Cnario Player 在Windows的任务管理器中, 找到启动标签栏, 从里面找到Cnari ...
- Vue.js 2.x笔记:状态管理Vuex(7)
1. Vuex简介与安装 1.1 Vuex简介 Vuex是为vue.js应用程序开发的状态管理模式,解决的问题: ◊ 组件之间的传参,多层嵌套组件之间的传参以及各组件之间耦合度过高问题 ◊ 不同状态中 ...
- 快速排序-python
- [题解]邮递员寄信(luoguP1629)
题目来源:luoguP1629 题目描述 有一个邮递员要送东西,邮局在结点1.他总共要送N-1样东西,其目的地分别是2-N.由于这个城市的交通比较繁忙,因此所有的道路都是单行的,共有M条道路,通过每条 ...
- reload ans current configure command
reload ans current configure command enable_ans_license.conf enable ans license WL enable ans licens ...
- Python unittest 测试输入(input)和输出(print)
Python 自带的 unittest 库可以用来写单元测试. 测试输入输出的解决方法是: 将标准输入输出定向到一个StringIO类(python3是 io.StringIO). import un ...