UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)
https://vjudge.net/problem/UVA-1599
给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色。求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小。一对结点可能有多条边,一条边可能连接相同的结点(自环)。输入保证结点1可以到达结点n。颜色是1~10^9的整数。
分析:
- 从题目中我们可以看出,题目中的无向图是可以出现自环和重边的,自环我们可以在输入的时候检查并排除,但是重边我们需要保留,并从中选择颜色最小的边。
- 题目的数据量很大,不可能采用邻接矩阵存储图,因此应采用邻接表,且邻接表便于进行bfs
- 路径的颜色不代表路径的权重,本题中路径是无权的
思路:
从终点开始倒着bfs一次,得到每个点到终点的距离,然后从起点开始,按照每次距离减1的方法寻找接下来的点的编号。按照颜色最小的走,如果有多个颜色最小,则都拉入队列中,将最小的颜色记录在res数组中。
其中,index=d[0]-d[u]就得到了当前u节点对应的距离,也就是步骤数。
细节:
- 已经进入队列的节点不能重复入队,否则复杂度太高,会tle(重复入队的复杂度至少是O(n^2),在n=100000的情况下直接tle)
- 第一次bfs和第二次bfs的终止时机不同,第一次找到起点就终止,第二次则是从队列中取出节点时才能终止,为的是遍历完所有导向终点且路径长度一致的边,只有这样才能结果正确
- d数组记录每个节点到终点n的距离,不能用0进行初始化,而终点处的初始化必须是0
- d数组不能不初始化,否则对于多输入题目,前面的输入可能影响后面的输出
1 #include <iostream>
2 #include <algorithm>
3 #include <string>
4 #include <sstream>
5 #include <set>
6 #include <vector>
7 #include <stack>
8 #include <map>
9 #include <queue>
10 #include <deque>
11 #include <cstdlib>
12 #include <cstdio>
13 #include <cstring>
14 #include <cmath>
15 #include <ctime>
16 #include <functional>
17 using namespace std;
18
19 #define maxn 100000
20 #define inf 0x7fffffff
21
22 typedef struct ver
23 {
24 int num, color; //边的另一端的结点编号 和 颜色
25 ver(int n, int c) : num(n), color(c) {}
26 } Ver;
27
28 int n, m, a, b, c;
29 int d[maxn], res[maxn]; //d记录每个点到终点的最短距离 res记录最短路的颜色
30 bool vis[maxn], inqueue[maxn]; //vis每个结点是否被访问过 inqueue标记结点是否加入了队列,防止重复加入
31 vector<Ver> edge[maxn]; //邻接表记录图
32
33 void bfs(int start, int end)
34 {
35 memset(inqueue, 0, n);
36 memset(vis, 0, n);
37 int u, v, c;
38 queue<int> q;
39 q.push(start);
40 if (start == 0) //用于正向BFS
41 {
42 memset(res, 0, sizeof(int) * n);
43 while (!q.empty())
44 {
45 u = q.front();
46 q.pop();
47 vis[u] = 1;
48 if (u == n - 1)
49 return;
50 int minc = inf, len = edge[u].size();
51 for (int i = 0; i < len; i++)
52 if (!vis[v = edge[u][i].num] && d[u] - 1 == d[v])
53 minc = min(edge[u][i].color, minc); //获取所有路径中最小的颜色
54 for (int i = 0; i < len; i++)
55 if (!vis[v = edge[u][i].num] && d[u] - 1 == d[v] && edge[u][i].color == minc && !inqueue[v])
56 q.push(v), inqueue[v] = 1; //若有多组颜色相同且未入队,则将其入队
57 int index = d[0] - d[u]; //获得当前步数对应的下标
58 if (res[index] == 0)
59 res[index] = minc;
60 else
61 res[index] = min(res[index], minc); //获取最小颜色
62 }
63 }
64 else
65 while (!q.empty()) //用于反向DFS 构建层次图,找最短路
66 {
67 u = q.front();
68 q.pop();
69 vis[u] = 1;
70 for (int i = 0, len = edge[u].size(); i < len; i++)
71 if (!vis[v = edge[u][i].num] && !inqueue[v])
72 {
73 d[v] = d[u] + 1; //一定是头一次入队,这通过inqueue保证
74 if (v == 0)
75 return; //找到起点退出
76 q.push(v); //如果不是起点,就把这个点入队
77 inqueue[v] = 1; //入队标记
78 }
79 }
80 }
81
82 int main()
83 {
84 while (scanf("%d%d", &n, &m) == 2)
85 {
86 for (int i = 0; i < n; i++)
87 edge[i].clear();
88 memset(d, -1, sizeof(int) * n);
89 d[n - 1] = 0; //初始化的细节
90 while (m--)
91 {
92 scanf("%d%d%d", &a, &b, &c);
93 if (a != b) //排除自环
94 {
95 edge[a - 1].push_back(ver(b - 1, c));
96 edge[b - 1].push_back(ver(a - 1, c));
97 }
98 }
99 bfs(n - 1, 0); //先反向BFS
100 bfs(0, n - 1); //再正向BFS
101 printf("%d\n%d", d[0], res[0]);
102 for (int i = 1; i < d[0]; i++)
103 printf(" %d", res[i]);
104 printf("\n");
105 }
106 return 0;
107 }
UVA 1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)的更多相关文章
- UVa1599 Ideal Path(双向bfs+字典序+非简单图的最短路+队列判重)
题目大意: 对于一个n个房间m条路径的迷宫(Labyrinth)(2<=n<=100000, 1<=m<=200000),每条路径上都涂有颜色,颜色取值范围为1<=c&l ...
- Uva 1599 Ideal Path - 双向BFS
题目连接和描述以后再补 这题思路很简单但还真没少折腾,前后修改提交了七八次才AC...(也说明自己有多菜了).. 注意问题: 1.看清楚原题的输入输出要求,刚了书上的中文题目直接开撸,以为输入输出都是 ...
- UVa 1599 Ideal Path【BFS】
题意:给出n个点,m条边,每条边上涂有一个颜色,求从节点1到节点n的最短路径,如果最短路径有多条,要求经过的边上的颜色的字典序最小 紫书的思路:第一次从终点bfs,求出各个节点到终点的最短距离, 第二 ...
- uva 1599 ideal path(好题)——yhx
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGYAAAODCAYAAAD+ZwdMAAAgAElEQVR4nOy9L8/0ypH/Pa8givGiyC
- UVA 1599 Ideal Path(bfs1+bfs2,双向bfs)
给一个n个点m条边(<=n<=,<=m<=)的无向图,每条边上都涂有一种颜色.求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小.一对 ...
- 【每日一题】 UVA - 1599 Ideal Path 字典序最短路
题解:给一个1e5个点2e5条边,每个边有一个值,让你输出一条从1到n边的路径使得:条数最短的前提下字典序最小. 题解:bfs一次找最短路(因为权值都是1,不用dijkstra),再bfs一次存一下路 ...
- UVa 1599 Ideal Path (两次BFS)
题意:给出n个点,m条边的无向图,每条边有一种颜色,求从结点1到结点n颜色字典序最小的最短路径. 析:首先这是一个最短路径问题,应该是BFS,因为要保证是路径最短,还要考虑字典序,感觉挺麻烦的,并不好 ...
- UVA 1599 Ideal Path (HDU 3760)
两次bfs: 第一次bfs逆向搜索,得到每个点到终点的最短距离,找出最短路:第二次bfs根据最短距离可以选择满足条件的最短路. 注意!碰到这种很大数据量的题目一定要记得用scanf,printf 输入 ...
- UVA 1599 Ideal Path
题意: 给出n和m,n代表有n个城市.接下来m行,分别给出a,b,c.代表a与b之间有一条颜色为c的道路.求最少走几条道路才能从1走到n.输出要走的道路数和颜色.保证颜色的字典序最小. 分析: bfs ...
随机推荐
- AQS学习(一)自旋锁原理介绍(为什么AQS底层使用自旋锁队列?)
1.什么是自旋锁? 自旋锁作为锁的一种,和互斥锁一样也是为了在并发环境下保护共享资源的一种锁机制.在任意时刻,只有一个执行单元能够获得锁. 互斥锁通常利用操作系统提供的线程阻塞/唤醒机制实现,在争用锁 ...
- const变量通过指针修改问题
const的变量在特定情况下可以通过指针修改,但是在另一些情况下是不能通过指针修改. 以下是VC6下才测试. 1. 不能修改的情况 #include int const a = 10; void ma ...
- STM32—PID控制在直流电机中的应用
文章目录 一.PID控制算法 1.什么是PID 2.PID系数的理解 Ⅰ.比例(P)部分 Ⅱ.积分(I)部分 Ⅲ.微分(D)部分 3.PID的数字化处理 二.位置闭环控制 三.速度闭环控制 一.PID ...
- SQL 练习9
查询学过「张三」老师授课的同学的信息 SELECT Student.* from Student,Teacher,Course,SC WHERE Teacher.TId = Course.TId AN ...
- 【设计模式】装饰者模式(DecoratorMode0
From: https://liudongdong1.github.io/ 装饰者模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实 ...
- 谷歌浏览器崩溃、电脑版微信,vscode打不开网页
家里的电脑使用64位win7,谷歌浏览器直接打开页面都会提示页面崩溃,电脑版微信打开页面链接为空白,vscode打开发行说明或插件说明显示空白,这一系列的问题好像都跟浏览器器有关,之前找了很多文章,都 ...
- ASP.NET Core教程:ASP.NET Core 程序部署到Windows系统
一.创建项目 本篇文章介绍如何将一个ASP.NET Core Web程序部署到Windows系统上.这里以ASP.NET Core WebApi为例进行讲解.首先创建一个ASP.NET Core We ...
- npm : 无法加载文件 C:\Program Files\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。
- Java常用类之时间类
JDK8之前日期时间API 1. java.lang.System类 2. java.util.Date类 3. java.text.SimpleDateFormat类 4. java.util.Ca ...
- AOP的底层实现-CGLIB动态代理和JDK动态代理
AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础.它是一种面向切面编程的思想.关于AOP的基础知识,相信多数童鞋都已经了如指掌,我们就略过这部分,来 ...