Luogu 2149 [SDOI2009]Elaxia的路线
感觉这题可以模板化。
听说spfa死了,所以要练堆优化dijkstra。
首先对$x_{1},y_{1},x_{2},y_{2}$各跑一遍最短路,然后扫一遍所有边看看是不是同时在两个点的最短路里面,如果是的话就把这条边加到一张新图中去,因为最短路一定没有环,所以最后造出来的这张新图一定是一个$DAG$,dp一遍求最长链即为答案。
考虑一下怎么判断一条边是否在最短路里,设这条边连接的两个点是$x$,$y$,边权是$v$,如果它在最短路里面,那么有$dis(x_{1}, x) + v + dis(y_{1}, y) == dis(x_{1}, y_{1})$并且$dis(x_{2}, x) + v + dis(y_{2}, y) == dis(x_{2}, y_{2})$,注意第二个条件中$x$和$y$可以交换。加边的时候注意维持一下$DAG$的形态,可以把$x$和$y$到$x_{1}$的距离小的向距离大的连边。
时间复杂度$O(nlogn)$,堆优化dij是瓶颈。
感觉写得很长。
Code:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
using namespace std;
typedef pair <int, int> pin; const int N = ;
const int M = 3e6 + ;
const int inf = 0x3f3f3f3f; int n, m, inx[M], iny[M], inv[M], deg[N], f[N], ans = ;
int c1, c2, c3, c4, tot = , head[N], dis[N], d[][N];
bool vis[N]; struct Edge {
int to, nxt, val;
} e[M << ]; inline void add(int from, int to, int val) {
e[++tot].to = to;
e[tot].val = val;
e[tot].nxt = head[from];
head[from] = tot;
} inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} inline void swap(int &x, int &y) {
int t = x; x = y; y = t;
} priority_queue <pin> Q;
void dij(int st) {
memset(dis, 0x3f, sizeof(dis));
memset(vis, , sizeof(vis));
Q.push(pin(dis[st] = , st));
for(; !Q.empty(); ) {
int x = Q.top().second; Q.pop();
if(vis[x]) continue;
vis[x] = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(dis[y] > dis[x] + e[i].val) {
dis[y] = dis[x] + e[i].val;
Q.push(pin(-dis[y], y));
}
}
}
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} int dfs(int x) {
if(vis[x]) return f[x];
vis[x] = ;
int res = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
chkMax(res, dfs(y) + e[i].val);
}
return f[x] = res;
} int main() {
read(n), read(m), read(c1), read(c2), read(c3), read(c4);
for(int i = ; i <= m; i++) {
read(inx[i]), read(iny[i]), read(inv[i]);
add(inx[i], iny[i], inv[i]), add(iny[i], inx[i], inv[i]);
} dij(c1); memcpy(d[], dis, sizeof(d[]));
dij(c2); memcpy(d[], dis, sizeof(d[]));
dij(c3); memcpy(d[], dis, sizeof(d[]));
dij(c4); memcpy(d[], dis, sizeof(d[])); /* for(int i = 1; i <= n; i++)
printf("%d ", d[0][i]);
printf("\n");
for(int i = 1; i <= n; i++)
printf("%d ", d[1][i]);
printf("\n");
for(int i = 1; i <= n; i++)
printf("%d ", d[2][i]);
printf("\n");
for(int i = 1; i <= n; i++)
printf("%d ", d[3][i]);
printf("\n"); */ tot = ; memset(head, , sizeof(head));
for(int i = ; i <= m; i++) {
int x = inx[i], y = iny[i], v = inv[i];
if(d[][x] + v + d[][y] == d[][c2])
if(d[][y] + v + d[][x] == d[][c4] || d[][x] + v + d[][y] == d[][c4]) {
if(d[][x] < d[][y]) {
add(x, y, v);
deg[y]++;
} else {
add(y, x, v);
deg[x]++;
}
} swap(x, y);
if(d[][x] + v + d[][y] == d[][c2])
if(d[][y] + v + d[][x] == d[][c4] || d[][x] + v + d[][y] == d[][c4]) {
if(d[][x] < d[][y]) {
add(x, y, v);
deg[y]++;
} else {
add(y, x, v);
deg[x]++;
}
}
} memset(vis, , sizeof(vis));
for(int i = ; i <= n; i++)
if(deg[i] == && !vis[i]) dfs(i); /* for(int i = 1; i <= n; i++)
printf("%d ", f[i]);
printf("\n"); */ for(int i = ; i <= n; i++)
chkMax(ans, f[i]); printf("%d\n", ans);
return ;
}
Luogu 2149 [SDOI2009]Elaxia的路线的更多相关文章
- Luogu P2149 [SDOI2009]Elaxia的路线(最短路+记忆化搜索)
P2149 [SDOI2009]Elaxia的路线 题意 题目描述 最近,\(Elaxia\)和\(w**\)的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们必须合理地安排两个人在一起的 ...
- 洛谷 2149 [SDOI2009]Elaxia的路线
题目描述 最近,Elaxia和w的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的 ...
- BZOJ1880或洛谷2149 [SDOI2009]Elaxia的路线
BZOJ原题链接 洛谷原题链接 显然最长公共路径是最短路上的一条链. 我们可以把最短路经过的边看成有向边,那么组成的图就是一张\(DAG\),这样题目要求的即是两张\(DAG\)重合部分中的最长链. ...
- Luogu P2149 [SDOI2009]Elaxia的路线 | 图论
题目链接 题解: 题面中给了最简洁清晰的题目描述:"求无向图中,两对点间最短路的最长公共路径". 对于这个问题我们可以先考虑图中的哪些边对这两对点的最短路产生了贡献. 比如说下面这 ...
- BZOJ 1880: [Sdoi2009]Elaxia的路线( 最短路 + dp )
找出同时在他们最短路上的边(dijkstra + dfs), 组成新图, 新图DAG的最长路就是答案...因为两人走同一条路但是不同方向也可以, 所以要把一种一个的s,t换一下再更新一次答案 ---- ...
- 【BZOJ1880】[Sdoi2009]Elaxia的路线(最短路)
[BZOJ1880][Sdoi2009]Elaxia的路线(最短路) 题面 BZOJ 洛谷 题解 假装我们知道了任意两点间的最短路,那么我们怎么求解答案呢? 不难发现公共路径一定是一段连续的路径(如果 ...
- 洛谷 P2149 [SDOI2009]Elaxia的路线 解题报告
P2149 [SDOI2009]Elaxia的路线 题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia ...
- 【BZOJ 1880】 [Sdoi2009]Elaxia的路线 (最短路树)
1880: [Sdoi2009]Elaxia的路线 Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. ...
- BZOJ1880: [Sdoi2009]Elaxia的路线(最短路)
1880: [Sdoi2009]Elaxia的路线 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 2049 Solved: 805 题目链接:https ...
随机推荐
- Hibernate Validator验证框架中@NotEmpty、@NotBlank、@NotNull 的区别
Hibernate Validator验证框架中@NotEmpty.@NotBlank.@NotNull的主要使用情况 @NotEmpty 用在集合类上面 @NotBlank 用在String上 ...
- 图片上传-本地图片转base64+ie8支持+本地预览支持
最近项目由于flash同学没在了,图片上传只能前端重新做,后台希望用base64数据上传,复用之前接口 问题来了, 1.ie8 不支持canvas转base64 2.本地预览 base64数据,ie8 ...
- CERC2016 爵士之旅 Jazz Journey
传送门(洛谷) 题目大意 给定$n$个位置,和一个长为$m$的序列$A$,你需要经过一条直接的边从第$A_i$个位置到第$A_{i+1}$个位置. 每条有向边$(u,v)$分为两种,第一种可以花费$C ...
- 在Arcmap中加载互联网地图资源的4种方法(转载)
前一段时间想在Arcmap中打开互联网地图中的地图数据,如影像数据.基础地图数据等,经过简单研究目前总结了四种方法,整理下与大家分享,有些内容可能理解有误,希望大家多多指教.4种方法如下: a) ...
- LoadRunner常见错误代码解决方案
一.LoadRunner26377错误 通常不是长度的问题,如果长度有问题就都出错了.应该是服务器返回的数据问题,导致没有找到这个参数. 26377错误的成因很多,总结最直接的结果就是No match ...
- Python函数-delattr()
delattr(object, name) 作用: 删除object对象名为name的属性. 参数object:对象. 参数name:属性名称字符串. >>> class Perso ...
- hihoCoder1296:约瑟夫问题
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho的班级正在进行班长的选举,他们决定通过一种特殊的方式来选择班长. 首先N个候选人围成一个圈,依次编号为0.. ...
- Windows Server 2008 R2换SID要注意
今天刚装Windows2008R2,准备做实验.同样,我对虚拟机采用了母盘和差异磁盘.在新建好的虚拟机上使用NewSID执行更新SID操作时,一切正常,但当更新完并重启进入系统后,竟然蓝屏了. 原 ...
- SQL子查询/嵌套查询
sql子查询 嵌套SELECT语句 嵌套SELECT语句也叫子查询,一个 SELECT 语句的查询结果能够作为另一个语句的输入值.子查询不但能够出现在Where子句中,也能够出现在from子句中,作为 ...
- 讯为开发板的最小LINUX系统烧写及U盘的挂载及卸载
fdisk -c 0 fatformat mmc 0:1ext3format mmc 0:2ext3format mmc 0:3ext3format mmc 0:4 fastboot fastboot ...