题目:

给一个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. 容器HashMap原理(学习)

    一.概述 基于哈希表的 Map 接口的非同步实现,允许使用 null 值和 null 键,不保证映射的顺序 二.数据结构 HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体:Has ...

  2. oracle type类型

    转载 http://blog.sina.com.cn/s/blog_6cfb6b090100ve92.html 转自网络,具体用法我会再细化 1.概念    方法:是在对象类型说明中用关键字  MEM ...

  3. js验证手机号,身份证,车牌号验证

    js验证手机号  <input type="text" class="identificationno"> // 身份证号码为15位或者18位,15 ...

  4. bzoj2115 [Wc2011] Xor——高斯消元 & 异或线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2115 异或两次同一段路径的权值,就相当于没有走这段路径: 由此可以得到启发,对于不同的走法, ...

  5. 基于ELK的传感器数据分析练习

    目录 Sensor Data Analytics Application 数据构成 数据模型设计 Logstash配置 Kibana可视化 Sensor Data Analytics Applicat ...

  6. javascript DOM基本操作

    javascript DOM基本操作 1.DOM(Document Object Model 文档对象模型) 2.节点: 文档节点:document 元素节点:html.head.body.title ...

  7. codevs1669(dfs)子集和目标值

    1692 子集和的目标值  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 给定n个整数in和目标值T,求某一非空子集 ...

  8. mysql之distinct

    记录一下这几天看mysql必知必会的小知识点: 关于mysql查询不同的行 比如记录表中 查询有多少个城市 可能查出很多城市 可以用distinct 来解决这个问题 SELECT DISTINCT c ...

  9. web界面bug-临时

    一.登录页面 二.首页 三.项目 四.项目池 五.专家管理 六.审批 七.日/周报 八.设置

  10. VF 查表

    题目的意思就是 给你一个数字 n (1~81)  然后问你从 1~10^9  之中有多少个 各位数字之和等于 n 的 数字 我上去   打表了  而且速度还差不多 , 能在 几十分钟内算出来所有答案 ...