题意:

给定一个有重边有自环的无向图,n个点(2 <= n <= 100000), m条边(1 <= m <= 200000), 每条边有一个权值, 求从第一个点到n的最少步数, 如果最少步数相同有多条路径, 那么输出权值字典序最小的一条。

分析:

用BFS解决最短路问题, 可以先从终点BFS, 求出每个点到终点的最短距离。 那么最少步数就是起点的最短距离, 最短路径就是从起点每次向最短距离比自己少1的顶点移动(如果有多个则可以随便走), 这样就可以保证走的是最短路径, 如果一开始我们是从起点BFS, 那么这样则不能保证走的是通往终点的最短路径。然后我们就可以从起点出发, 循环最短距离次, 每次选择字典序最少的走,  如果有多个字典序相同则选择多个, 直到走完最短距离, 就可以得出答案。 注意两次BFS都需要添加标记, 不然重边很可能就会导致TLE。

 #include <bits/stdc++.h>
using namespace std;
const int maxm = 1e7;
const int maxn = 1e6 + ;
const int inf = 1e9;
struct Node{
int v,col,next;
Node():v(),col(),next(){}
};
struct ele{
int v;
int dist;
ele(int v, int dist):v(v),dist(dist){}
}; Node edge[maxn];
int G[maxn], d[maxn];
bool vis[maxn];
int n, m, cnt; void build(){
memset(G,-,sizeof(G));
cnt = ;
for(int i = ; i < m; i++){
int u, v, col;
scanf("%d %d %d", &u, &v, &col);
if(u == v) continue;
edge[cnt].v = v;
edge[cnt].col = col;
edge[cnt].next = G[u];
G[u] = cnt++;
edge[cnt].v = u;
edge[cnt].col = col;
edge[cnt].next = G[v];
G[v] = cnt++;
}
} void revbfs(){
fill(d,d+maxn, inf);
memset(vis,,sizeof(vis));
queue<ele> q;
q.push(ele(n,));
d[n] = ;
vis[n] = ;
while(!q.empty()){
ele u = q.front(); q.pop();
d[u.v] = u.dist;
for(int i = G[u.v]; i != -; i = edge[i].next){
int v = edge[i].v;
if(d[v] < u.dist + || vis[v]){
continue;
}
q.push(ele(v,u.dist+));
vis[v] = ;
}
}
}
void bfs(){
vector<int> path;
memset(vis,,sizeof(vis));
vis[] = ;
vector<int> next;
next.push_back();
for(int i = ; i < d[]; i++){//the essential minimum step
int min_col = inf;
for(int j = ; j < next.size(); j++){
int u = next[j];
for(int k = G[u]; k != -; k = edge[k].next){
int v = edge[k].v;
if(d[u] == d[v] + )
min_col = min(min_col,edge[k].col);
}
}
//find out the minimum color
path.push_back(min_col); vector<int> next2;
for(int j = ; j < next.size(); j++){
int u = next[j];
for(int k = G[u]; k != -; k= edge[k].next){
int v = edge[k].v;
if(d[u] == d[v] + && !vis[v] && edge[k].col == min_col){
vis[v] = ;
next2.push_back(v);
}
}
}
next = next2;
} printf("%d\n%d",(int)path.size(),path[]);
for(int i = ; i < path.size(); i++){
printf(" %d",path[i]);
}
puts("");
}
int main(){
freopen("1.txt","r",stdin);
while(~scanf("%d %d", &n, &m)){
build();
revbfs();//反向bfs求出终点到每个点的最短距离
bfs();
}
printf("%.3f",(double)clock()/CLOCKS_PER_SEC);
return ;
}

UVa 1599 理想路径(反向BFS 求最短路径 )的更多相关文章

  1. UVA 816 -- Abbott's Revenge(BFS求最短路)

     UVA 816 -- Abbott's Revenge(BFS求最短路) 有一个 9 * 9 的交叉点的迷宫. 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可).进入一个交叉 ...

  2. UVa 1599 Ideal Path【BFS】

    题意:给出n个点,m条边,每条边上涂有一个颜色,求从节点1到节点n的最短路径,如果最短路径有多条,要求经过的边上的颜色的字典序最小 紫书的思路:第一次从终点bfs,求出各个节点到终点的最短距离, 第二 ...

  3. UVA 1599, POJ 3092 Ideal Path 理想路径 (逆向BFS跑层次图)

    大体思路是从终点反向做一次BFS得到一个层次图,然后从起点开始依次向更小的层跑,跑的时候选则字典序最小的,由于可能有多个满足条件的点,所以要把这层满足条件的点保存起来,在跑下一层.跑完一层就会得到这层 ...

  4. Uva 1599 最佳路径

    题目链接:https://uva.onlinejudge.org/external/15/1599.pdf 题意: 保证在最短路的时候,输出字典序最小的路径. 方法: 路径上有了权值,可以利用图论的数 ...

  5. Uva 1599 Ideal Path - 双向BFS

    题目连接和描述以后再补 这题思路很简单但还真没少折腾,前后修改提交了七八次才AC...(也说明自己有多菜了).. 注意问题: 1.看清楚原题的输入输出要求,刚了书上的中文题目直接开撸,以为输入输出都是 ...

  6. 理想路径——双向BFS

    题目 给n个点m条边(2 ≤ n ≤ 100000,1 ≤ m ≤ 200000)的无向图,每条边上都涂有一种颜色.求从结点1到结点n的一条路径,使得经过的边数尽量的少,在此前提下,经过边的颜色序列的 ...

  7. BFS - 求最短路径

    Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. ...

  8. 图-用DFS求连通块- UVa 1103和用BFS求最短路-UVa816。

    这道题目甚长, 代码也是甚长, 但是思路却不是太难.然而有好多代码实现的细节, 确是十分的巧妙. 对代码阅读能力, 代码理解能力, 代码实现能力, 代码实现技巧, DFS方法都大有裨益, 敬请有兴趣者 ...

  9. UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)

    https://vjudge.net/problem/UVA-1599 给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色 ...

随机推荐

  1. redis的多实例

    redis的多实例功能,可以在一个机器上,启动多个redis服务端 vim redis.conf ,写入以下内容(不要加上注释) port 6379 bind 0.0.0.0 daemonize no ...

  2. Windows下安装Ubuntu16.04双系统

    ROS需要在Ubuntu系统上开发,虚拟机跑Ubuntu开发ROS容易出现各种各样的问题,所以需要安装Ubuntu16.04双系统.笔者也是一步步按着网上的帖子来,由于网上的教程都不是最新的而且有的也 ...

  3. 找规律 UVALive 6506 Padovan Sequence

    题目传送门 /* 找规律:看看前10项就能看出规律,打个表就行了.被lld坑了一次:( */ #include <cstdio> #include <algorithm> #i ...

  4. [C#基础知识系列]专题十:全面解析可空类型[转]

    原文链接 主要内容: 1:空合并操作符(?? 操作符) ??操作符也就是"空合并操作符",它代表的意思是两个操作数,如果左边的数不为null时,就返回左边的数,如果左边的数为nul ...

  5. HBuilder的默认工作空间的修改

    HBuilder的默认工作空间的修改并不像其他ide一样,在设置里进行更改,而是在工具中进行设置. 1.单击菜单栏“工具”,选择“变更默认代码存放目录” 2.进行修改即可.

  6. 421 Maximum XOR of Two Numbers in an Array 数组中两个数的最大异或值

    给定一个非空数组,数组中元素为 a0, a1, a2, … , an-1,其中 0 ≤ ai < 231 .找到 ai 和aj 最大的异或 (XOR) 运算结果,其中0 ≤ i,  j < ...

  7. sdut2355Binary Search Heap Construction

    链接 捣鼓了一下午..按堆建树 写完交 返回TLE..数据不大 感觉不会超了 无奈拿了数据来看什么奇葩数据会超 发现数据跟我输出不一样 看了好久才明白理解错题意了 给出的字符串有两个标签 按前一个来建 ...

  8. SQL Server中行列转置方法

    PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PIVOT(聚合函数(列) FOR 列 in (…) )AS P ...

  9. C++模版完全解析

    模版 模版在C++中是一个很重要的概练,生活中的模版也是随处可见,比如制造工程师会 哪一个模子去构造出一个一个的工件,C++程序员能够用模版去实例化y有相同操作 不同类型的函数或者数据结构.简单的理解 ...

  10. 判断Exe(DLL)和符号文件是否匹配---验证模块和符号文件是否匹配的工具和方法

    当我们进行程序调试时,有时调试器会直接告诉你符号文件不对,或则显示出的调用栈不对,当你怀疑符号文件不匹配时,如何确定呢? 如果是用windbg调试,请用 !chksym 模块名比如,匹配的时候  不匹 ...