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. PHP小知识总结(1)

    1. mysqli_query — 对数据库执行一次查询 失败时返回 FALSE ,通过 mysqli_query() 成功执行SELECT, SHOW, DESCRIBE或 EXPLAIN查询会返回 ...

  2. 数据库lib7第2, 3题(创建索引和触发器)

    2. 分别为上述建立的表格建立适当的索引,请描述建立索引的过程(可以截图或者写SQL).其中,要求对SPJ标中的SNo, PNo字段各建立一个索引,为(PNo, JNo)的组合建立一个索引.请问,SN ...

  3. Struts → 《Struts2程序开发》教材大纲

  4. Android实战:手把手实现“捧腹网”APP(二)-----捧腹APP原型设计、实现框架选取

    Android实战:手把手实现"捧腹网"APP(一)-–捧腹网网页分析.数据获取 Android实战:手把手实现"捧腹网"APP(二)-–捧腹APP原型设计.实 ...

  5. Android 系统字体和颜色样式

    Android 字体和颜色 对于能够显示文字的控件(如TextView EditText RadioButton Button CheckBox Chronometer等等),你有时需要控制字体的大小 ...

  6. JavaScript 验证API

    约束验证 DOM 方法 Property Description checkValidity() 如果 input 元素中的数据是合法的返回 true,否则返回 false. setCustomVal ...

  7. qt中窗口绘制——图片的绘制

    在qt 中,QPixmap 用于表示一张图片,支持png,jpg格式的加载. QPixmap pm("c:/test.png"); 或者 QPixmap pm; pm.load(& ...

  8. @loj - 2174@ 「FJOI2016」神秘数

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 一个可重复数字集合 S 的神秘数定义为最小的不能被 S 的子集的 ...

  9. 8-2udp和tcp网络编程以及粘包和解决粘包的方法

    一  tcp网络编程 server 端 import socket sk=socket.socket() #实例化一个对象 sk.setsockopt(socket.SOL_SOCKET,socket ...

  10. oracle函数 sqrt(x)

    [功能]返回x的平方根 [参数]x数字型表达式 [返回]数字 [示例] select sqrt(64),sqrt(10) from dual; 返回:8 , 3.16227766