【POJ】2449.Remmarguts' Date(K短路 n log n + k log k + m算法,非A*,论文算法)
题解
(搬运一个原来博客的论文题)
抱着板题的心情去,结果有大坑
就是S == T的时候也一定要走,++K
我发现按照论文写得\(O(n \log n + m + k \ log k)\)算法没有玄学A*快,不开心啊(或者我松教水平不高啊)
论文里主要是怎么样呢,把所有边反向,从T开始求最短路,然后求一个最短路树,求法就是把新边权改成
原来的边权 + 终点最短路 - 起点最短路
如果新边权是0,那么这条边就在最短路树里,如果有很多条边边权是0就随便选一条
然后我们对于每个点走一条不同于最短路的路径,发现是走过的非树边的边权加上S到T的最短路
我们记录每个点拓展出去的边都有哪些,拓展出去的边从小到大排序,一个点同时可以拓展它父亲可以拓展的边
这样我们可以用一个可持久化左偏树来维护,按照左儿子右兄弟的方法扩展,删掉一个点然后把左右儿子合起来选次大,或者再从当前点走一条非树边
不过删掉一个点把左右儿子加进去也可以
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <cmath>
#define MAXN 5005
#define PII pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define eps 1e-8
//#define ivorysi
using namespace std;
typedef long long int64;
int N,M,St,T,K,dis[MAXN];
vector<PII > G[MAXN],G_rev[MAXN];
vector<int> son[MAXN];
int fa[MAXN];
bool vis[MAXN],ct[MAXN];
PII line[200005];
struct cmp1 {
bool operator ()(const PII &a, const PII &b) {
return a.se > b.se;
}
};
struct Left_Tree {
Left_Tree *lc,*rc;
int v,to,dis;
}pool[8000005],*tail = pool;
vector<Left_Tree*> rt[MAXN];
struct node {
int s,t,cnt,v1,v0;
friend bool operator < (const node &a,const node &b) {
if(a.v1 != b.v1) return a.v1 < b.v1;
else if(a.v0 != b.v0) return a.v0 < b.v0;
else if(a.s != a.s) return a.s < b.s;
else return a.t < b.t;
}
};
multiset<node> S;
priority_queue<PII,vector<PII >,cmp1> Q;
Left_Tree *Newnode(PII k) {
Left_Tree *res = tail++;
res->v = k.se;res->to = k.fi;
res->lc = res->rc = NULL;
res->dis = 0;
return res;
}
int get_dist(Left_Tree *r) {
if(!r) return -1;
else return r->dis;
}
Left_Tree* Merge(Left_Tree *A,Left_Tree *B) {
if(!A) return B;
if(!B) return A;
if(A->v > B->v) swap(A,B);
Left_Tree *res = tail++;
*res = *A;
res->rc = Merge(A->rc,B);
if(get_dist(res->lc) < get_dist(res->rc)) swap(res->lc,res->rc);
res->dis = get_dist(res->rc) + 1;
return res;
}
Left_Tree* build(int u,int tot) {
if(u > tot) return NULL;
Left_Tree *res = Newnode(line[u]);
res->lc = build(u << 1,tot);
res->rc = build(u << 1 | 1,tot);
if(get_dist(res->lc) < get_dist(res->rc)) swap(res->lc,res->rc);
res->dis = get_dist(res->lc) + 1;
return res;
}
void dfs(int u) {
int tot = 0;
for(int i = 0 ; i < G[u].size() ; ++i) {
PII k = G[u][i];
if(ct[k.fi]) continue;
if(k.se != 0 || vis[u]) {
line[++tot] = k;
int t = tot;
while(t != 1) {
if(line[t].se < line[t >> 1].se) {
swap(line[t],line[t >> 1]);
t >>= 1;
}
else break;
}
}
else vis[u] = 1;
}
rt[u].pb(build(1,tot));
if(fa[u]) rt[u][0] = Merge(rt[u][0],rt[fa[u]][0]);
for(int i = 0 ; i < son[u].size() ; ++i) dfs(son[u][i]);
}
void Dijkstra() {
for(int i = 1 ; i <= N ; ++i) dis[i] = 0X7fffffff;
dis[T] = 0;
Q.push(mp(T,0));
while(!Q.empty()) {
PII u = Q.top();Q.pop();
if(vis[u.fi]) continue;
vis[u.fi] = 1;
for(int i = 0 ; i < G_rev[u.fi].size() ; ++i) {
PII k = G_rev[u.fi][i];
if(!vis[k.fi] && u.se + k.se < dis[k.fi]) {
dis[k.fi] = u.se + k.se;
Q.push(mp(k.fi,dis[k.fi]));
}
}
}
}
void Init() {
scanf("%d%d",&N,&M);
int s,t,c;
for(int i = 1 ; i <= M ; ++i) {
scanf("%d%d%d",&s,&t,&c);
G[s].pb(mp(t,c));
G_rev[t].pb(mp(s,c));
}
scanf("%d%d%d",&St,&T,&K);
Dijkstra();
for(int i = 1 ; i <= N ; ++i) {
if(dis[i] == 0x7fffffff) {ct[i] = 1;continue;}
for(int j = 0 ; j < G[i].size() ; ++j) {
G[i][j].se += dis[G[i][j].fi] - dis[i];
if(G[i][j].se == 0 && !fa[i]) {
fa[i] = G[i][j].fi;
son[fa[i]].pb(i);
}
}
}
memset(vis,0,sizeof(vis));
dfs(T);
}
void Solve() {
Init();
if(dis[St] == 0x7fffffff) {puts("-1");return;}
if(St == T) ++K;
if(K == 1) {printf("%d\n",dis[St]);return;}
if(rt[St][0]) {
S.insert((node){St,rt[St][0]->to,0,rt[St][0]->v,0});
}
int C = K - 2;
while(C && !S.empty()) {
C--;
node Now = *S.begin();
S.erase(S.begin());
while(rt[Now.s].size() <= Now.cnt + 1) {
int s = rt[Now.s].size() - 1;
rt[Now.s].pb(Merge(rt[Now.s][s]->lc,rt[Now.s][s]->rc));
}
if(rt[Now.s][Now.cnt + 1]) {
S.insert((node){Now.s,rt[Now.s][Now.cnt + 1]->to,Now.cnt + 1,Now.v0 + rt[Now.s][Now.cnt + 1]->v,Now.v0});
}
if(rt[Now.t][0]){
S.insert((node){Now.t,rt[Now.t][0]->to,0,Now.v1 + rt[Now.t][0]->v,Now.v1});
}
}
if(C || S.empty()) {
puts("-1");
}
else {
node Now = *S.begin();
printf("%d\n",Now.v1 + dis[St]);
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
【POJ】2449.Remmarguts' Date(K短路 n log n + k log k + m算法,非A*,论文算法)的更多相关文章
- poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)
http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Subm ...
- POJ 2449 - Remmarguts' Date - [第k短路模板题][优先队列BFS]
题目链接:http://poj.org/problem?id=2449 Time Limit: 4000MS Memory Limit: 65536K Description "Good m ...
- poj 2449 Remmarguts' Date (k短路模板)
Remmarguts' Date http://poj.org/problem?id=2449 Time Limit: 4000MS Memory Limit: 65536K Total Subm ...
- poj 2449 Remmarguts' Date K短路+A*
题目链接:http://poj.org/problem?id=2449 "Good man never makes girls wait or breaks an appointment!& ...
- 图论(A*算法,K短路) :POJ 2449 Remmarguts' Date
Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 25216 Accepted: 6882 ...
- poj 2449 Remmarguts' Date 第k短路 (最短路变形)
Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 33606 Accepted: 9116 ...
- poj 2449 Remmarguts' Date(K短路,A*算法)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013081425/article/details/26729375 http://poj.org/ ...
- K短路模板POJ 2449 Remmarguts' Date
Time Limit: 4000MS Memory Limit: 65536K Total Submissions:32863 Accepted: 8953 Description &qu ...
- POJ 2449 Remmarguts' Date (K短路 A*算法)
题目链接 Description "Good man never makes girls wait or breaks an appointment!" said the mand ...
- POJ 2449 Remmarguts' Date(第k短路のA*算法)
Description "Good man never makes girls wait or breaks an appointment!" said the mandarin ...
随机推荐
- LINUX 线程
1.使用进程技术的优势(1)CPU时分复用,单核心CPU可以实现宏观上的并行(2)实现多任务系统需求(多任务的需求是客观的)2.进程技术的劣势(1)进程间切换开销大(2)进程间通信麻烦而且效率低3.解 ...
- Hadoop生态圈-hbase介绍-伪分布式安装
Hadoop生态圈-hbase介绍-伪分布式安装 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.HBase简介 HBase是一个分布式的,持久的,强一致性的存储系统,具有近似最 ...
- addEventListener() 事件监听
addEventListener() 用于向指定元素添加事件. 可以向一个元素添加多次事件或者多次不同事件,后面的事件是不会覆盖前面的. 语法: element.addEventListener(ev ...
- Ubuntu如何同步网络时间
解决方法: 1.安装ntpdate工具 apt-get install ntpdate 2.将系统时间与网络同步 ntpdate cn.pool.ntp.org 3.将时间写入硬件 hwclock - ...
- bzoj千题计划133:bzoj3130: [Sdoi2013]费用流
http://www.lydsy.com/JudgeOnline/problem.php?id=3130 第一问就是个最大流 第二问: Bob希望总费用尽量大,那肯定是把所有的花费加到流量最大的那一条 ...
- bzoj千题计划122:bzoj1034: [ZJOI2008]泡泡堂BNB
http://www.lydsy.com/JudgeOnline/problem.php?id=1034 从小到大排序后 最大得分: 1.自己最小的>对方最小的,赢一场 2.自己最大的>对 ...
- Linux IO模型
1. Linux IO 模型矩阵 2. 同步阻塞IO 3. 同步非阻塞IO 4. 异步阻塞IO 5. 异步非阻塞IO
- 什么是EOF -- 转
转载地址:http://www.ruanyifeng.com/blog/2011/11/eof.html 我学习C语言的时候,遇到的一个问题就是EOF. 它是end of file的缩写,表示&quo ...
- HSL
说明: HSL(H,S,L) 取值: H: Hue(色调).0(或360)表示红色,120表示绿色,240表示蓝色,也可取其他数值来指定颜色.取值为:0 - 360 S: Saturation(饱和度 ...
- 20155303 2016-2017-2 《Java程序设计》第九周学习总结
20155303 2016-2017-2 <Java程序设计>第九周学习总结 目录 学习内容总结(Linux命令) 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考 ...