A*:我已经忘了怎么写了,反正n=30,m=1000都能卡掉。。。

正解:可持久化左偏树+堆维护可能集合

原论文:http://www.docin.com/p-1387370338.html

概括:

结论:

1.t为根求最短路树T,定义P'为路径s-t的路径P和T没有交集的部分,P’和P都是有序边集

对于P'中相邻边一定存在tail和head的祖先后代关系(或者重合)

2.新定义边的代价:dis[v]+w-dis[u],即换边走的额外可能花费

这样一个P就是:dis[1~n]+∑e∈P' newweight[e]

3.P和P'一一对应。

求法:

1.T为根求最短路树

2.非树边放进u的左偏树内,

3.dfs可持久化合并堆,得到到根路径上的出边的堆

4.堆维护四元组(u,v,pos,val)边集倒数第二条边tail是u,倒数第一条边tail是v,v的这个边的左偏树节点编号pos,P’的代价val

更新:

A.v找到rt[v]最小的加入P的末尾

B.u找到rt[u]下一个最小的边作为新的v和pos,这个边一定是pos的左儿子或者右儿子

初始:(0,1,*,0)要特判

注意特判:

A.rt[v]=0?

B.pos没有左右儿子?

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;
while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);
(fl==true)&&(x=-x);
}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{
const int N=;
const int M=+;
int n,m;
double E;
struct node{
int nxt,to;
double val;
}e[M];
int hd[N],cnt=;
void add(int x,int y,double z){
e[++cnt].nxt=hd[x];
e[cnt].to=y;e[cnt].val=z;
hd[x]=cnt;
} struct edge{
int x,y;
double z;
}b[M];
double dis[N];
struct po{
int x;double val;
po(){}
po(int xx,double vv){
x=xx;val=vv;
}
bool friend operator <(po a,po b){
return a.val>b.val;
}
};
priority_queue<po>q;
bool vis[N];
int pre[N];
void dij(){
memset(dis,,sizeof dis);
dis[n]=;
q.push(po(n,));
while(!q.empty()){
po now=q.top();q.pop();
if(vis[now.x]) continue;
int x=now.x;
vis[x]=;
for(reg i=hd[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;
pre[y]=i;
q.push(po(y,dis[y]));
}
}
}
}
bool on[M];
struct tr{
int ls,rs;
int d,id;
double val;
tr(){}
tr(double v,int ddd){
ls=,rs=;val=v;d=;id=ddd;
}
}t[M*];
int tot;
int rt[N];
int merge(int x,int y,int typ){
if(!x||!y) return x+y;
if(t[x].val>t[y].val) swap(x,y);
if(typ){
int nw=++tot;
t[nw]=t[x];
x=nw;
}
t[x].rs=merge(t[x].rs,y,typ);
if(t[t[x].ls].d<t[t[x].rs].d) swap(t[x].ls,t[x].rs);
t[x].d=t[t[x].rs].d+;
return x;
}
struct sol{
int u,v,pos;
double val;
sol(){}
sol(int uu,int vv,int pp,double vd){
u=uu;v=vv;pos=pp;val=vd;
}
bool friend operator <(sol a,sol b){
return a.val>b.val;
}
};
void dfs(int x){
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
rt[y]=merge(rt[y],rt[x],);
dfs(y);
}
}
priority_queue<sol>hp; int main(){
rd(n);rd(m);scanf("%lf",&E);
for(reg i=;i<=m;++i){
rd(b[i].x);rd(b[i].y);scanf("%lf",&b[i].z);
add(b[i].y,b[i].x,b[i].z);
}
dij();
// for(reg i=1;i<=n;++i){
// cout<<i<<" : "<<dis[i]<<endl;
// }
memset(hd,,sizeof hd);
cnt=;
for(reg i=;i<n;++i){
on[pre[i]]=;
int id=pre[i];
add(b[id].y,b[id].x,b[id].z);
}
for(reg i=;i<=m;++i){
if(!on[i]){
t[++tot]=tr(dis[b[i].y]+b[i].z-dis[b[i].x],i);
rt[b[i].x]=merge(rt[b[i].x],tot,);
}
}
dfs(n);
hp.push(sol(,,-,));
double st=dis[];
ll ans=;
while(!hp.empty()){
sol now=hp.top();hp.pop();
E-=now.val+st;
if(E<) break;
++ans;
int u=now.u,v=now.v;
if(now.v==&&now.u==){
if(rt[]){
sol lp=now;
lp.u=;
lp.pos=rt[];
lp.val=t[rt[]].val;
lp.v=b[t[rt[]].id].y;
hp.push(lp);
}
}else{
if(rt[now.v]){
sol lp=now;
lp.u=v;
lp.pos=rt[lp.u];
lp.val+=t[rt[lp.u]].val;
lp.v=b[t[rt[lp.u]].id].y;
hp.push(lp);
}
if(t[now.pos].ls){
sol lp=now;
lp.pos=t[lp.pos].ls;
lp.val+=t[lp.pos].val-t[now.pos].val;
lp.v=b[t[lp.pos].id].y;
hp.push(lp);
}
if(t[now.pos].rs){
sol lp=now;
lp.pos=t[lp.pos].rs;
lp.val+=t[lp.pos].val-t[now.pos].val;
lp.v=b[t[lp.pos].id].y;
hp.push(lp);
}
}
}
ot(ans);
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
*/

[学习笔记]k短路的更多相关文章

  1. 学习笔记——k近邻法

    对新的输入实例,在训练数据集中找到与该实例最邻近的\(k\)个实例,这\(k\)个实例的多数属于某个类,就把该输入实例分给这个类. \(k\) 近邻法(\(k\)-nearest neighbor, ...

  2. R语言学习笔记—K近邻算法

    K近邻算法(KNN)是指一个样本如果在特征空间中的K个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性.即每个样本都可以用它最接近的k个邻居来代表.KNN算法适 ...

  3. 【学习笔记】K 短路问题详解

    \(k\) 短路问题简介 所谓"\(k\) 短路"问题,即给定一张 \(n\) 个点,\(m\) 条边的有向图,给定起点 \(s\) 和终点 \(t\),求出所有 \(s\to t ...

  4. bzoj 1598: [Usaco2008 Mar]牛跑步 [k短路 A*] [学习笔记]

    1598: [Usaco2008 Mar]牛跑步 题意:k短路 ~~貌似A*的题目除了x数码就是k短路~~ \[ f(x) = g(x) + h(x) \] \(g(x)\)为到达当前状态实际代价,\ ...

  5. A* k短路 学习笔记

    题目大意 n个点,m条边有向图,给定S,T,求不严格k短路 n<=1000 m<=100000 k<=1000 不用LL 分析 A*算法 f(i)表示从S出发经过i到T的估价函数 \ ...

  6. K短路 学习笔记

    K短路,顾名思义,是让你求从$s$到$t$的第$k$短的路. 暴力当然不可取,那么我们有什么算法可以解决这个问题? -------------------------- 首先,我们要维护一个堆. st ...

  7. [原创]java WEB学习笔记71:Struts2 学习之路-- struts2常见的内建验证程序及注意点,短路验证,非字段验证,错误消息的重用

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  8. 算法笔记--次小生成树 && 次短路 && k 短路

    1.次小生成树 非严格次小生成树:边权和小于等于最小生成树的边权和 严格次小生成树:    边权和小于最小生成树的边权和 算法:先建好最小生成树,然后对于每条不在最小生成树上的边(u,v,w)如果我们 ...

  9. 学习笔记之Java程序设计实用教程

    Java程序设计实用教程 by 朱战立 & 沈伟 学习笔记之JAVA多线程(http://www.cnblogs.com/pegasus923/p/3995855.html) 国庆休假前学习了 ...

随机推荐

  1. Python datetime模块的其他方法

  2. mysql更改密码

    mysql command line client输入密码以后闪退问题的解决: 网上搜到的解决办法(my.ini文件之类的修改对我都没有起到作用).. 所以觉得是自己密码的问题,因为许久不用这个软件了 ...

  3. goland的下载安装破解并配置

    1.下载地址:https://www.jetbrains.com/go/ 2.安装:简单 3.破解:https://www.cnblogs.com/igoodful/p/9113946.html 4. ...

  4. C++程序设计教材目录思维导图(增C++Primer)

    正在做C++思维导图,大工程,比较艰苦. 先做了三个C++教材目录的思维导图.C++教材不等于C++,这个容易些.看思维导图,整理所学知识,这个可以会. 给出三张图,对应三种教材: 谭浩强. C++程 ...

  5. 数据库 Mysql-mongodb-redis

    目录 1. Mysql 1.1. 介绍 1.1.1 基础 1.1.3 数据库操作 1.2. 查询 1.2.1 条件 1.2.2 聚合 1.2.3 分组 1.2.4 排序 1.2.4 分页 1.3. 高 ...

  6. 跨域知识(一)——CORS

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing). 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从 ...

  7. Oracle函数——MINUS

    解释 “minus”直接翻译为中文是“减”的意思,在Oracle中也是用来做减法操作的,只不过它不是传统意义上对数字的减法,而是对查询结果集的减法.A minus B就意味着将结果集A去除结果集B中所 ...

  8. 用预编译包安装zabbix-agent

    如果主机无法上网,安装rpm又缺少依赖时,可以通过预编译包进行安装zabbix-agent,下载地址 https://www.zabbix.com/download 下载后,执行如下命令: wget ...

  9. Java练习 SDUT-3338_计算各种图形的周长(接口与多态)

    计算各种图形的周长(接口与多态) Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 定义接口Shape,定义求周长的方法l ...

  10. HDU_1061:Rightmost Digit

    Problem Description Given a positive integer N, you should output the most right digit of N^N.   Inp ...