2. 旅行计划

★★   输入文件:djs.in   输出文件:djs.out   简单对比
时间限制:3 s   内存限制:128 MB

【题目描述】

过暑假了,阿杜准备出行旅游,他已经查到了某些城市的两两之间的距离及可行路线(可行路线有方向),如下图所示。请你编程计算从阿杜所住城市到其它城市的最短路径以帮助阿杜制定旅行计划。

【输入格式】

输入由若干行组成,第一行有三个整数 n(1≤n≤100) 为城市数,m(1≤m≤n2) 为城市间道路数,s(0≤s≤n−1) 是阿杜所住城市。第 2 至 m+1 行是每条路的信息,每行三个整数,为道路的起点、终点和两城市间距离。(城市从 0 开始编号)

【输出格式】

输出 n 组(按城市编号由小至大),每组三行

第一行:城市编号及一个冒号

第二行:path及一个冒号,后面是最短路径节点编号序列(编号间用一个空格隔开)

第三行:cost及一个冒号,后面是一个整数,表示路径距离

如果没有通路则输出 no

【输入样例】

6 8 0
0 2 10
0 4 30
0 5 100
1 2 5
2 3 50
3 5 10
4 3 20
4 5 60

【输出样例】

0:
no
1:
no
2:
path:0 2
cost:10
3:
path:0 4 3
cost:50
4:
path:0 4
cost:30
5:
path:0 4 3 5
cost:60

自动选择评测机
 
gcc/g++4.8.5
gcc/g++4.8.5 -O2
gcc/g++4.8.5(C++11)
gcc/g++4.6.3
gcc/g++4.6.3 -O2

提交代码 Pascal C C++

看到评论区的一群大佬的评论 我立刻不淡定了  决定来瞅瞅(探头探脑   这一道据说很坑的题 没想到想了3分钟 敲了4分钟 完美AC!

那么这一道题到底应该咋做

我的时间复杂度是(mlogm  +  n^2)n<100  m<10000  这个时间复杂度看起来还是 很棒的

首先很简单 我们要来按照题目中给出的单向边和起点 跑一遍dijkstra  这是O(n)的

然后重点在于怎样输出路径

在之前的时候总是看到别人的代码里有一个非常神奇的数组是path  然而我并没有学过这么难的东西(俺可是初学者--哈哈)

首先我们最暴力的想法肯定是O(n^3)的

对于每一个点 从剩下的点里面 看一下哪一个点是他的前驱

很显然这一道题n^3也没啥问题

但是蒟蒻拒绝!

所以我们想办法压缩到O(n^2)

听起来不错

既然我们浪费时间主要在找前驱  那么我们只需要在dijkstra的过程中顺便用一个pathpre数组来存每一个点的前驱  后面直接跑一个递归调用一下下就好啦

具体看代码 还是非常好理解的优化(这是蒟蒻自己发明的!请求专利)

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define pa pair<int,int>
#define maxn 115
using namespace std;
int n,m,s;
int dis[maxn],vis[maxn],pathpre[maxn];
vector<int> v[maxn],w[maxn];
priority_queue< pa,vector<pa>,greater<pa> > q;
inline int read()
{
int X=; bool flag=; char ch=getchar();
while(ch<''||ch>'') {if(ch=='-') flag=; ch=getchar();}
while(ch>=''&&ch<='') {X=(X<<)+(X<<)+ch-''; ch=getchar();}
if(flag) return X;
return ~(X-);
}
inline void write(int X)
{
if(X<) {X=~(X-); putchar('-');}
if(X>) write(X/);
putchar(X%+'');
}
void Dijkstra()
{
memset(dis,0x3f,sizeof(dis));
dis[s]=;
q.push(make_pair(,s));
while(!q.empty()){
int rt=q.top().second;
q.pop();
if(vis[rt]) continue;
vis[rt]=;
for(int i=;i<v[rt].size();i++){
int to=v[rt][i];
if(dis[to]>dis[rt]+w[rt][i]){
dis[to]=dis[rt]+w[rt][i];
pathpre[to]=rt;
q.push(make_pair(dis[to],to));
}
}
}
}
bool flagfinish=false;
void path_out(int rt){//最差时间复杂度:O(mlogm+n^2)
if(rt==s){
write(rt);printf(" ");
flagfinish=true;
return;
}
// for(int i=0;i<v[rt].size();i++)
// if(dis[v[rt][i]]==dis[rt]+w[rt][i]){ 错
// path_out(v[rt][i]);
// write(rt);printf(" ");
// return;
// }
path_out(pathpre[rt]);write(rt);printf(" ");
}
int main()
{
freopen("djs.in","r",stdin);
freopen("djs.out","w",stdout);
n=read(),m=read(),s=read();
for(int i=,x,y,z;i<=m;i++)
{
x=read(),y=read(),z=read();
v[x].push_back(y);w[x].push_back(z);
}
Dijkstra();
for(int i=;i<n;i++)
{
write(i);puts(":");
if(dis[i]==inf||i==s) puts("no");
else
{
printf("path:");path_out(i);printf("\n");
printf("cost:%d\n",dis[i]);flagfinish=false;
}
}
return ;
}

cogs 2. 旅行计划 dijkstra+打印路径小技巧的更多相关文章

  1. COGS 2. 旅行计划

    2. 旅行计划 ★☆   输入文件:djs.in   输出文件:djs.out   简单对比时间限制:3 s   内存限制:128 MB 过暑假了,阿杜准备出行旅游,他已经查到了某些城市的两两之间的距 ...

  2. 紧急救援 L2-001 dijkstra 打印路径 最短路条数 权值

    较为复杂的dijkstra 包含路径打印  最小路的条数  最小路径的情况下取最大权值 v0要是标记就会出错...? 有权值的题目  不能设置mp[i][i]为0  否则会无限加权 这题很有参考价值 ...

  3. 一个人的旅行(用小技巧转化为dijkstra算法)

    注意: 1:因为两点之间可能有多条路,所以更新路径长度的时候做一次判断 if(time < mat[a][b]) mat[a][b] = mat[b][a] = time; 2:因为主函数中的数 ...

  4. L2-001. 紧急救援 (Dijkstra算法打印路径)

    作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当其他城市有紧急求 ...

  5. 牛客-小a的旅行计划 + 数学推导

    小a的旅行计划 题意: 小a终于放假了,它想在假期中去一些地方游玩,现在有N个景点,编号为,同时小b也想出去游玩.由于一些特殊♂原因,他们的旅行计划必须满足一些条件 首先,他们可以从这N个景点中任意选 ...

  6. 牛客ACM赛 B [小a的旅行计划 ]

    链接 B 小a的旅行计划 把\(n\)个数中选任意数分成\(a,b\)两个集合,集合无区别,要求不包含且有交,求方案数.\(n\leq 10^{13}\) 首先讨论\(a,b\)并集是否为全集: 若是 ...

  7. 【51Nod】1273 旅行计划 树上贪心

    [题目]51Nod 1273 旅行计划 [题意]给定n个点的树和出发点k,要求每次选择一个目的地旅行后返回,使得路径上未访问过的点最多(相同取编号最小),旅行后路径上所有点视为访问过,求旅行方案.\( ...

  8. 51nod 1273 旅行计划——思维题

    某个国家有N个城市,编号0 至 N-1,他们之间用N - 1条道路连接,道路是双向行驶的,沿着道路你可以到达任何一个城市.你有一个旅行计划,这个计划是从编号K的城市出发,每天到达一个你没有去过的城市, ...

  9. 51nod-1273: 旅行计划

    [传送门:51nod-1273] 简要题意: 给出一棵树,点数为n,现在你有一个旅行计划,从k城市出发,每天前往一个没去过的城市,并且旅途中经过的没有去过的城市尽可能的多(如果有2条路线,经过的没有去 ...

随机推荐

  1. [转][Linux/Ubuntu] vi/vim 使用方法讲解

    vi/vim 基本使用方法 vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的 ...

  2. CodeForces 1204E"Natasha, Sasha and the Prefix Sums"(动态规划 or 组合数学--卡特兰数的应用)

    传送门 •参考资料 [1]:CF1204E Natasha, Sasha and the Prefix Sums(动态规划+组合数) •题意 由 n 个 1 和 m 个 -1 组成的 $C_{n+m} ...

  3. python基础四之列表

    列表详解 列表的增删改查! 增加 li = ['zxc', 'is', 'a'] # append 在列表结尾整体添加 修改列表,但是没有返回值 li.append('boy') print(li) ...

  4. 写一个js配合rem

    rem.js 目前笔者解决移动端的尺寸带来的样式问题,都是通过viewport + rem的.viewport 相信大家都用过了,而rem需要用js动态设置html的字体大小. 动态设置rem的根字体 ...

  5. H3C 用三层交换机实现VLAN间路由

  6. H3C 三种生成树协议特性的比较

  7. POJ 3311 Hie with the Pie 兼 Codevs 2800 送外卖(动态规划->TSP问题)

    Description The Pizazz Pizzeria prides itself in delivering pizzas to its customers as fast as possi ...

  8. zookeeper(1)-概述

    ZooKeeper概述 ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现.它提供了简单原始的功能,分布式应用可以基于它实现更高级 ...

  9. Linux 内核设备属性

    sysfs 中的设备入口可有属性. 相关的结构是: struct device_attribute { struct attribute attr; ssize_t (*show)(struct de ...

  10. C#调用smtp邮件发送几个大坑

    1.网易.新浪邮箱新增了一个叫“授权码”的东西,开通smtp服务时,必须开启授权码,并且邮件发送代码中也需要加上授权码,如下代码: //指定邮箱账号和密码,需要注意的是,这个密码是你在邮箱设置里开启服 ...