k短路(A*)
http://poj.org/problem?id=2449
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=1e3+; /**
求第K短的算法基于BFS搜索,当终点出队K次时,所走的总距离就是第K短路,
不过这样那些不该走的路会被反复的走,造成许多空间时间浪费,这时候就要用到启发式的A*搜索
**/ ///from s to t
///opp:from t to s struct node
{
int d,len;
node *next;
}*e[maxn],*oppe[maxn]; ///h:from this point to destination(predict must:predict<actual)
///g:from source to this point(actual)
int h[maxn],unreach; struct rec
{
int d,dist;
bool operator<(const rec &b) const
{
return b.dist<dist;
}
};
priority_queue<rec>st; struct noa
{
int d,dist,pre;
bool operator<(const noa &b) const
{
if (b.pre==pre)
return b.dist<dist;
return b.pre<pre;
}
};
priority_queue<noa>ast; bool vis[maxn];
int s,t,ind,ci[maxn]; int astar()
{
int d,dist;
node *p;
///多组数据时需要
// while (!ast.empty())
// ast.pop();
if (h[s]!=unreach)
ast.push({s,,h[s]});
while (!ast.empty())
{
d=ast.top().d;
dist=ast.top().dist;
ast.pop();///!
ci[d]++;
if (ci[d]==ind && d==t)
return dist;///而不是ast.top().dist
///优化
if (ci[d]>ind)
continue; p=e[d];
while (p)
{
if (h[p->d]!=unreach)
///aster
ast.push({p->d,dist+p->len,dist+p->len+h[p->d]});
///just dijkstra
// ast.push({p->d,dist+p->len,dist+p->len});
p=p->next;
}
}
return -;
} void opp_dijkstra()
{
int d,dd;
node *p;
memset(h,0x7f,sizeof(h));
unreach=h[];
h[t]=;
st.push({t,});
while ()
{
while (!st.empty() && vis[st.top().d])
st.pop();
if (st.empty())
break;
d=st.top().d;
st.pop();
vis[d]=;
p=oppe[d];///
while (p)
{
dd=p->d;
if (h[dd]>h[d]+p->len)
{
h[dd]=h[d]+p->len;
st.push({dd,h[dd]});
}
p=p->next;
}
}
} int main()
{
int a,b,c,n,m,i;
node *p;
scanf("%d%d",&n,&m);
for (i=;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
p=new node();
p->d=b;
p->len=c;
p->next=e[a];
e[a]=p; p=new node();
p->d=a;
p->len=c;
p->next=oppe[b];
oppe[b]=p;
}
scanf("%d%d%d",&s,&t,&ind);
///!!!
if (s==t)
ind++;
// ///shortest path
// scanf("%d%d",&s,&t);
// ind=1;
opp_dijkstra();
printf("%d",astar());
return ;
}
/*
2 2
1 2 1
2 1 1
1 1 1 3 3
1 2 1
2 3 2
3 2 1
1 1 1 3 3
1 2 1
2 3 2
3 1 3
1 1 2 3 1
1 2 3
1 3 1 3 2
1 2 10
2 3 2
1 3 1 3 2
1 2 10
2 3 2
1 3 2 4 4
1 3 2
3 2 5
1 4 3
4 2 1
1 2 2 x
4 4
1 2 100000
2 3 1
3 2 1
3 4 100000
1 4 1000 3 4
1 2 1
2 1 2
2 3 1
3 2 1
2 3 5 3 3
1 2 1000
1 3 1
3 2 1
1 2 1 */
https://www.luogu.org/problemnew/show/P2483
68分……
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=5e3+; struct node
{
int d;
double len;
node *next;
}*e[maxn],*oppe[maxn]; ///h:from this point to destination(predict must:predict<actual)
///g:from source to this point(actual)
double h[maxn],unreach;
double tot; struct rec
{
int d;
double dist;
bool operator<(const rec &b) const
{
return b.dist<dist;
}
};
priority_queue<rec>st; struct noa
{
int d,g;
double dist,pre;
bool operator<(const noa &b) const
{
if (b.pre==pre)
return b.dist<dist;
return b.pre<pre;
}
};
priority_queue<noa>ast; bool vis[maxn];
int s,t,ind,re,n,m;
int ci[maxn]; void aster()
{
int d,dd,g;
double dist,ddist;
node *p;
ind=tot/h[];///限制次数 if (h[s]!=unreach)
ast.push({s,,,h[s]});
while (!ast.empty())
{
d=ast.top().d;
dist=ast.top().dist;
g=ast.top().g;
ast.pop();///!
ci[d]++;
if (d==t)
{
if (dist>tot)
return;
tot-=dist;
re++;
ind=re+tot/dist;///限制次数,优化
continue; ///这题的坑爹地方:到达终点,就不能再走了
} p=e[d];
while (p)
{
dd=p->d;
ddist=dist+p->len;
if (h[dd]!=unreach && g!=m && ci[dd]<ind && ddist<=tot)
ast.push({dd,g+,ddist,ddist+h[p->d]});
p=p->next;
}
}
} void opp_dijkstra()
{
int d,dd,i;
node *p;
unreach=1.0e11;
for (i=;i<=n;i++)
h[i]=unreach; h[t]=;
st.push({t,});
while ()
{
while (!st.empty() && vis[st.top().d])
st.pop();
if (st.empty())
break;
d=st.top().d;
st.pop();
vis[d]=;
p=oppe[d];///
while (p)
{
dd=p->d;
if (h[dd]>h[d]+p->len)
{
h[dd]=h[d]+p->len;
st.push({dd,h[dd]});
}
p=p->next;
}
}
} int main()
{
int a,b,i;
double c;
node *p,*pp;
scanf("%d%d",&n,&m);
scanf("%lf",&tot);
for (i=;i<=m;i++)
{
scanf("%d%d%lf",&a,&b,&c);
p=new node();
p->d=b;
p->len=c;
p->next=e[a];
e[a]=p; p=new node();
p->d=a;
p->len=c;
p->next=oppe[b];
oppe[b]=p;
}
s=,t=n;
opp_dijkstra();
///lower the memory
for (i=;i<=n;i++)
{
p=oppe[i];
while (p)
{
pp=p;
p=p->next;
free(pp);
}
}
aster();
printf("%d",re);
return ;
}
k短路(A*)的更多相关文章
- POJ 2449 Remmarguts' Date --K短路
题意就是要求第K短的路的长度(S->T). 对于K短路,朴素想法是bfs,使用优先队列从源点s进行bfs,当第K次遍历到T的时候,就是K短路的长度. 但是这种方法效率太低,会扩展出很多状态,所以 ...
- POJ 2449Remmarguts' Date K短路模板 SPFA+A*
K短路模板,A*+SPFA求K短路.A*中h的求法为在反图中做SPFA,求出到T点的最短路,极为估价函数h(这里不再是估价,而是准确值),然后跑A*,从S点开始(此时为最短路),然后把与S点能达到的点 ...
- BZOJ-1975 魔法猪学院 K短路 (A*+SPFA)
1975: [Sdoi2010]魔法猪学院 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1323 Solved: 433 [Submit][Statu ...
- 【POJ】2449 Remmarguts' Date(k短路)
http://poj.org/problem?id=2449 不会.. 百度学习.. 恩. k短路不难理解的. 结合了a_star的思想.每动一次进行一次估价,然后找最小的(此时的最短路)然后累计到k ...
- poj 2449 Remmarguts' Date K短路+A*
题目链接:http://poj.org/problem?id=2449 "Good man never makes girls wait or breaks an appointment!& ...
- 第k短路
poj 2449 模板题 A*+spfa #include<iostream> #include<cstdio> #include<cstring> #inclu ...
- poj 2449(A*求第K短路)
题目链接:http://poj.org/problem?id=2449 思路:我们可以定义g[x]为源点到当前点的距离,h[x]为当前点到目标节点的最短距离,显然有h[x]<=h*[x](h*[ ...
- K短路
K短路 用dijsktra+A*启发式搜索当点v第K次出堆的时候,这时候求得的路径是k短路.A*算法有一个启发式函数f(p)=g(p)+h(p), 即评估函数=当前值+当前位置到终点的最短距离g(p) ...
- poj 2449 Remmarguts' Date(第K短路问题 Dijkstra+A*)
http://poj.org/problem?id=2449 Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Subm ...
- bzoj 1975 [Sdoi2010]魔法猪学院(k短路)
题目描述 iPig在假期来到了传说中的魔法猪学院,开始为期两个月的魔法猪训练.经过了一周理论知识和一周基本魔法的学习之后,iPig对猪世界的世界本原有了很多的了解:众所周知,世界是由元素构成的:元素与 ...
随机推荐
- 如何通过stat获取目录或文件的权限的数字形式
man stat 查看帮助. -c --format=FORMAT use the specified FORMAT instead of the default; output a new line ...
- Java多线程4:Thread中的静态方法
一.Thread类中的静态方法 Thread类中的静态方法是通过Thread.方法名来调用的,那么问题来了,这个Thread指的是哪个Thread,是所在位置对应的那个Thread嘛?通过下面的例子可 ...
- python设计模式第五天【单例模式】
1. 定义 一个类只有一个实例,提供访问该实例的全局方法 2.应用场景 (1)多线程之间共享对象资源 (2)整个程序空间中的全局变量,共享资源 (3)大规模程序的节省创建对象的时间 3.代码实现(使用 ...
- 数据驱动-参数化(Parameters)
在录制程序运行的过程中,Vugen(脚本生成器)自动生成了脚本以及录制过程中实际用到的数据.在这个时候,脚本和数据是混在一起的. 在登录操作中,很明显xpj与123123是填入的数据,如果Contro ...
- 页面传递的都是string ; 每个标签要有name的原因是为了取值 因为传递给后台是键值对的形式
页面传递的都是string ; 每个标签要有name的原因是为了取值 因为传递给后台是键值对的形式
- ffmpeg 转码命令与ffplay
ffmpeg.exe用于视频的转码. ▫ 最简单的命令 ffmpeg -i input.avi -b:v 640k output.ts 该命令将当前文件夹下的input.avi文件转换为output. ...
- Luogu4725 【模板】多项式对数函数(NTT+多项式求逆)
https://www.cnblogs.com/HocRiser/p/8207295.html 安利! #include<iostream> #include<cstdio> ...
- SQL Server查询优化器的工作原理
SQL Server的查询优化器是一个基于成本的优化器.它为一个给定的查询分析出很多的候选的查询计划,并且估算每个候选计划的成本,从而选择一个成本最低的计划进行执行.实际上,因为查询优化器不可能对每一 ...
- 安装PHP 类库PEAR
PHP扩展与应用库常识 当php项目里没有pear时: 单独安装解决方案 下载下面连接的文件至go-pear.phar.http://pear.php.net/go-pear.phar该文件最好放到P ...
- 解决nginx发布网站跨目录访问
解决nginx发布网站跨目录访问(thinkphp5+lnmp) 到:usr/local/nginx/conf/vim fastcgi.cof 把最后一行加上井号#注释掉保存重启 restart 参考 ...