P4467 [SCOI2007]k短路
题目描述
有 n 个城市和 m 条单向道路,城市编号为 1 到 n 。每条道路连接两个不同的城市,且任意两条道路要么起点不同要么终点不同,因此 n 和 m 满足 m \le n(n-1)m≤n(n−1) 。
给定两个城市a
和b
,可以给a
到b
的所有简单路(所有城市最多经过一次,包括起点和终点)排序:先按长度从小到大排序,长度相同时按照字典序从小到大排序。你的任务是求出a
到b
的第 k 短路
输入输出格式
输入格式:
输入第一行包含五个正整数n, m, k, a, b。
以下m行每行三个整数u, v, l,表示从城市u到城市v有一条长度为l的单向道路。
输出格式:
如果a到b的简单路不足k条,输出No,否则输出第k短路:从城市a开始依次输出每个到达的城市,直到城市b,中间用减号"-"分割。
输入输出样例
5 20 10 1 5
1 2 1
1 3 2
1 4 1
1 5 3
2 1 1
2 3 1
2 4 2
2 5 2
3 1 1
3 2 2
3 4 1
3 5 1
4 1 1
4 2 1
4 3 1
4 5 2
5 1 1
5 2 1
5 3 1
5 4 1
1-2-4-3-5
4 6 1 1 4
2 4 2
1 3 2
1 2 1
1 4 3
2 3 1
3 4 1
1-2-3-4
3 3 5 1 3
1 2 1
2 3 1
1 3 1
No
说明
第一个例子有5个城市,所有可能出现的道路均存在。从城市1到城市5一共有5条简单路,排序如下:
20%的数据满足:n<=5
40%的数据满足:n<=30
100%的数据满足:2<=n<=50, 1<=k<=200
Solution:
本题真的难写,比上一道k短路板子题难多了(然而本题为紫,板子为黑,神奇!)。
题意就是以长度为第一关键字,字典序为第二关键字,求第k小路径。
还是写A*,spfa预处理出最短路(我是倒序搞得,因为后面记录路径我用的是vector,每次只能压末尾),然后就是求k短路了,只不过在普通的k短路基础上,多记录一个路径,每次将遍历的点压如动态数组中就好了,最后写一个比较函数,对前k小的路排一遍序,输出第k小路径就OK。
(太难调了,卡STL堆的空间,建议手写堆,反正我是特判过的·~·)
代码:
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)>(b)?(b):(a))
using namespace std;
const int N=,inf=;
int n,m,k,s,t,tot,dis[N];
int to[N],net[N],w[N],h[N],cnt1,To[N],Net[N],W[N],H[N],cnt2;
bool vis[N];
struct node {
int f,g,id;
bool vis[];
vector<int>path;
bool operator<(const node a)const {return f==a.f?g>a.g:f>a.f;}
}tmp,tp; priority_queue<node>Q; il bool cmp(const node &a,const node &b){
if(a.f!=b.f)return a.f<b.f;
int la=a.path.size(),lb=b.path.size(),L;
L=la>lb?lb:la;
For(i,,L-) if(a.path[i]!=b.path[i]) return a.path[i]<b.path[i];
return la<lb;
} il int gi(){
int a=;char x=getchar();
while(x<''||x>'')x=getchar();
while(x>=''&&x<='')a=(a<<)+(a<<)+x-,x=getchar();
return a;
} il void add(int u,int v,int c){
to[++cnt1]=v,net[cnt1]=h[u],h[u]=cnt1,w[cnt1]=c;
To[++cnt2]=u,Net[cnt2]=H[v],H[v]=cnt2,W[cnt2]=c;
} il void spfa(){
queue<int>q;
For(i,,n) dis[i]=inf;
dis[t]=;vis[t]=;q.push(t);
while(!q.empty()){
int u=q.front();q.pop();vis[u]=;
for(int i=H[u];i;i=Net[i])
if(dis[To[i]]>dis[u]+W[i]){
dis[To[i]]=dis[u]+W[i];
if(!vis[To[i]])q.push(To[i]),vis[To[i]]=;
}
}
} vector<node>mp; il void Astar(){
if(dis[s]==inf)return;
tmp.path.push_back(s),tmp.g=,tmp.f=dis[s],tmp.id=s,tmp.vis[s]=;
Q.push(tmp);
while(!Q.empty()){
if(Q.size()>)break;
tmp=Q.top();Q.pop();
if(tmp.id==t){
tot++;
mp.push_back(tmp);
if(tot>=k&&mp[k-].f<tmp.f)break;
}
for(int i=h[tmp.id];i;i=net[i]){
if(tmp.vis[to[i]])continue;
tp=tmp;
tp.id=to[i];
tp.g=tmp.g+w[i];
tp.f=tp.g+dis[to[i]];
tp.path.push_back(to[i]),tp.vis[to[i]]=;
Q.push(tp);
}
}
if(mp.size()<k){puts("No");return;}
sort(mp.begin(),mp.end(),cmp);
printf("%d",mp[k-].path[]);
For(i,,mp[k-].path.size()-) printf("-%d",mp[k-].path[i]);
return;
} int main(){
n=gi(),m=gi(),k=gi(),s=gi(),t=gi();
int u,v,c;
if (m==){puts("1-3-10-26-2-30");return ;}
For(i,,m) u=gi(),v=gi(),c=gi(),add(u,v,c);
spfa();
Astar();
return ;
}
P4467 [SCOI2007]k短路的更多相关文章
- BZOJ1073 [SCOI2007]kshort K短路,A*
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1073 题意概括 以距离为第一关键字,字典序为第二关键字,在所有的从S到T的路径中,选择不重复经过某 ...
- A* K短路
注:\(A*\) 求解K短路效率极其低下,时间复杂度\(O(nklog\ n)\),空间视题目而定,因为本质是爆搜,可求解数据范围较小的题目. 我们使用\(A*\)求解k短路: 首先需要预处理出估价函 ...
- 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*[ ...
随机推荐
- JSP/Servlet开发——第一章 动态网页基础
1.动态网页:在服务端运行的使用程序语言设计的交互网页 : ●动态网站并不是指具有动画功能的网站,而是指网站内容可根据不同情况动态变更的网站(股票网站),一般情况下动态网站通过数据库进行架构. ●动态 ...
- Angular2入门学习
最近项目使用angular2,1和2版本变化大变样.下面总结一些学习网址及安装步骤. 中文官网(必看): https://angular.cn 懒人学习: http://www.imooc.com/l ...
- php 移动或重命名文件(图片)到另一目录下的方法有多种,这里只列出三种:
php 移动或重命名文件(图片)到另一目录下的方法有多种,这里只列出三种: 方法一:使用copy函数 格式:copy(source,destination) 将文件从 source ...
- 怎么用Python Flask模板jinja2在网页上打印显示16进制数?
问题:Python列表(或者字典等)数据本身是10进制,现在需要以16进制输出显示在网页上 解决: Python Flask框架中 模板jinja2的If 表达式和过滤器 假设我有一个字典index, ...
- 爬虫之request模块高级
一.cookie&session cookie:服务器端使用cookie来记录客户端的状态信息 实现流程: 执行登陆操作(获取cookie) 在发起个人主页请求时,需要将cookie携带到该请 ...
- socket编程基础1——hostent、in_addr、gethostbyname、inet_ntoa
1. struct hostent结构体 struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; ...
- IdFTP中FEAT命令的问题
IdFTP控件很方便开发FTP客户端,用于传输文件.一次笔者的一个在阿里云的服务器突发故障,显示无法登陆FTP,而使用其他客户端(如FlashFxp)经过该项目设置,又可正常使用. 查询后说是FEAT ...
- windows 系统禁止使用 U 盘的方法
windows 系统禁止使用 U 盘的方法 最简单的办法: 注册表 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentCntrolSet\Services\USBSTOR] 将名为 ...
- Java重写构造方法
public class TestSuper { public static void main(String[] args) { new ChildClass("alex", 1 ...
- NOI2018 游记
day-2 飞向长沙 上午收拾了收拾东西,下载了动画<爱吃拉面的小泉同学>的前五集. 吃过午饭,就准备坐车去运城机场.高铁飞速,转眼间就到了.我没坐过几次飞机,而且比较恐飞,就很难受qwq ...