题目:

给一个n个点m条边(2≤m≤100000, 1≤m≤200000)的无向图,每条边上都涂有一种颜色(用1到1000000000表示)。求从结点1到结点n的一条路径,

使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小。一对结点间可能有多条边,一条边可能连接两个相同结点。输入保证结点1可以

到达结点n。

思路:

看到边数尽量少,颜色序列字典序最小,知道这是用BFS来做这个题。但是一直卡在怎么处理颜色的字典序最小上。看了答案之后知道先逆向处理每个节点到终点

的距离d[ i ],然后在正向分层BFS找出颜色最小的一条路径。

1.逆向处理距离d[]数组。

2.正向分层BFS根据当前结点的d[i]与下一个结点的d[i+1]之间差1来得出颜色字典序最小的一条路径。

这里我一开始使用队列来写的,但是这种写法在一层中找最小的颜色的时候是只找了一个结点,这就导致了得出的答案中的颜色不一定是同一条路径上的。

例如下面这个例子:

6 6
1 2 1
1 3 1
2 4 3
3 5 2
4 6 4
5 6 5

正确的答案应该是1,2,5,而我写出的答案却是1,2,4,苦思无果到网上看了下大佬的博客自己才写出来。

既然是分层BFS那么这种情况我们可以用循环遍历每一层,在每一层中用一个vector数组来存一下这一层中的所有的节点,

在这些节点中查找最小的颜色,然后处理这个最小颜色下面的边连接的点,更新这个vector数组知道结束。

代码:

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define MAX 1000000009
#define FRE() freopen("in.txt","r",stdin)
#define FRO() freopen("out.txt","w",stdout)
using namespace std;
typedef long long ll;
const int maxn = ;
int n,m,d[maxn],vis[maxn];
struct Edge {
int to,color;
Edge(int to,int color) {
this->to = to;
this->color = color;
}
};
vector<Edge>mp[maxn]; void BFS_reverse() {//逆向简单的BFS求最短路径。各个边的权值为1
memset(vis,,sizeof(vis));
d[n] = ;
vis[n] = ;
queue<int> que;
que.push(n);
while(!que.empty()) {
int u = que.front();
que.pop();
for(int i = ; i<mp[u].size(); i++) {
Edge e = mp[u][i];
if(vis[e.to]==) {
vis[e.to] = ;
d[e.to] = d[u]+;
que.push(e.to);
}
}
}
} void BFS() {
memset(vis,,sizeof(vis));
vector<int> next;
next.push_back();
vector<int> ans;
for(int k = ; k<d[]; k++) {//遍历这个图中所有的层次
int mmin = MAX; for(int i=; i<next.size(); i++) {//从这一层中的所有的节点中找到最小的颜色
int u = next[i];
for(int j=; j<mp[u].size(); j++) {
Edge e = mp[u][j];
if(d[e.to]+==d[u]) {
mmin = min(mmin, e.color);
}
}
} ans.push_back(mmin);//将答案颜色保存
vector<int> temp; for(int i=; i<next.size(); i++) {//保存与最小颜色连接且处于下一层的结点
int u = next[i];
for(int j=; j<mp[u].size(); j++) {
Edge e = mp[u][j];
if(d[u]==d[e.to]+ && vis[e.to]== && e.color==mmin) {
temp.push_back(e.to);
vis[e.to] = ;
}
}
}
next = temp;//更新next数组
}
printf("%d\n",ans.size());
printf("%d",ans[]);
for(int i=; i<ans.size(); i++) {
printf(" %d",ans[i]);
}
printf("\n");
return;
} int main() {
//FRE();
//FRO();
while(scanf("%d%d",&n,&m)!=EOF) {
memset(d,,sizeof(d));
for(int i=; i<*n; i++) {//一定要注意这里的范围,一晚上找错误就卡死在这里了
mp[i].clear();
}
for(int i = ; i<m; i++) {
int st,en,color;
scanf("%d%d%d",&st,&en,&color);
mp[st].push_back(Edge(en,color));
mp[en].push_back(Edge(st,color));
}
BFS_reverse();
BFS();
}
return ;
}

UVA-1599 Ideal Path(双向BFS)的更多相关文章

  1. Uva 1599 Ideal Path - 双向BFS

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

  2. UVa 1599 Ideal Path【BFS】

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

  3. UVA 1599 Ideal Path(bfs1+bfs2,双向bfs)

    给一个n个点m条边(<=n<=,<=m<=)的无向图,每条边上都涂有一种颜色.求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小.一对 ...

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

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

  5. UVa 1599 Ideal Path (两次BFS)

    题意:给出n个点,m条边的无向图,每条边有一种颜色,求从结点1到结点n颜色字典序最小的最短路径. 析:首先这是一个最短路径问题,应该是BFS,因为要保证是路径最短,还要考虑字典序,感觉挺麻烦的,并不好 ...

  6. UVA 1599 Ideal Path (HDU 3760)

    两次bfs: 第一次bfs逆向搜索,得到每个点到终点的最短距离,找出最短路:第二次bfs根据最短距离可以选择满足条件的最短路. 注意!碰到这种很大数据量的题目一定要记得用scanf,printf 输入 ...

  7. uva 1599 ideal path(好题)——yhx

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABGYAAAODCAYAAAD+ZwdMAAAgAElEQVR4nOy9L8/0ypH/Pa8givGiyC

  8. UVA 1599 Ideal Path

    题意: 给出n和m,n代表有n个城市.接下来m行,分别给出a,b,c.代表a与b之间有一条颜色为c的道路.求最少走几条道路才能从1走到n.输出要走的道路数和颜色.保证颜色的字典序最小. 分析: bfs ...

  9. 【每日一题】 UVA - 1599 Ideal Path 字典序最短路

    题解:给一个1e5个点2e5条边,每个边有一个值,让你输出一条从1到n边的路径使得:条数最短的前提下字典序最小. 题解:bfs一次找最短路(因为权值都是1,不用dijkstra),再bfs一次存一下路 ...

  10. POJ——3126Prime Path(双向BFS+素数筛打表)

    Prime Path Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 16272   Accepted: 9195 Descr ...

随机推荐

  1. TC SRM 597 DEV2

    第一次玩TC的SRM,只完成了一题,有点失落,不过还是要把每个问题都研究清楚才是我的本性,呵呵 第一题思路: 任意一个数,不断除掉2以后的剩下的数若相同则YES否则NO 第二题: 最开始判断字母个数是 ...

  2. HTTPS数据包抓取的可行性分析

    HTTPS数据包抓取的可行性分析 相信只要是从事软件开发, 多多少少都会涉及到数据包的抓取.常见的有网页数据抓取(即网页爬虫),应用程序数据包抓取等.网页数据抓取比较简单, 在chrome下可以非常方 ...

  3. [luogu2620]虫洞

    https://www.zybuluo.com/ysner/note/1284536 题面 给一个一维坐标系,出发点为\(0\),目标点为\(w\). 每\(1\)秒可以往后移不超过\(s\)个单位距 ...

  4. STM32: TIMER门控模式控制PWM输出长度

    搞了两天单脉冲没搞定,无意中发现,这个利用主从模式的门控方式来控制一路PWM的输出长度很有效. //TIM2 PWM输出,由TIM4来控制其输出与停止 //frequency_tim2:TIM2 PW ...

  5. 【167】IDL 中相关技巧

    IDL 中相关技巧 1. 注释:分号“;”表示注释内容的开始. 2. 续行:最后一个字符是“$”,那么本行将紧接着下一行,续行标志.(换行符,$+回车) 3. 中文编码:窗口>首选项>常规 ...

  6. 15_activity生命周期方法说明

    现在是可见并且可以被操作,所以现在是一个前台的Activity. 按一下Home键,它是先onPause然后onStop. 现在它就处于一个Stop停止的状态.停止的状态如果我当前内存够用的情况下,它 ...

  7. PCB 帆软FineReport安装,布署,配置

    公司使用帆软FineReport做为报表平台工具也有一年多时间,而FineReport报表平台与Tomcat Web应用服务是站队在java阵营里,因为相信拥抱微软;.net未来发展会越来越好,所以对 ...

  8. vim 跳行查看日志

    VIM 跳跃行号 一.显示行号 在命令模式下输入 :set nu   或者   :set number 即可显示行号 二.跳跃行号 在编辑模式下输入 ngg 或者 nG [n为指定的行数(如25)] ...

  9. C++ 类中的3种权限作用范围

    三种访问权限 public:可以被任意实体访问 protected:只允许子类及本类的成员函数访问 private:只允许本类的成员函数访问 #include <iostream> #in ...

  10. C++小项目-吃豆子游戏

    GMap.h #pragma once //保证头文件只被编译一次 #include "stdafx.h" #define MAP_LEN 19 //逻辑地图大小 (逻辑地图由行. ...