题目:

给一个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. ubuntu安装Android Studio

    参考 https://developer.android.com/guide/?hl=zh-CN 下载 https://developer.android.com/studio/?hl=zh-CN 解 ...

  2. 【POJ 1804】 Brainman

    [题目链接] 点击打开链接 [算法] 本题是一个很经典的问题 : 归并排序求逆序对数,可以用分治算法解决 分治,分而治之,分治算法的思想就是将一个问题转化为若干个子问题,对这些子问题分别求解,最后, ...

  3. 阿里Java开发规约笔记

    借助阿里开发规约,回顾一下Java开发编码基础方面的知识,结合自己使用中遇到的问题,记录一下规约中以前翻过的错.有共鸣的问题. 1.覆写方法时要加上@Override注解.重写一个类型T的equals ...

  4. Ural 1158. Censored! 有限状态自动机+DP+大整数

    Ural1158 看上去很困难的一道题. 原文地址 http://blog.csdn.net/prolightsfxjh/article/details/54729646 题意:给出n个不同的字符,用 ...

  5. Oracle强杀进程

      1.找到sid,serial#: SELECT /*+ rule */ s.username, l.type, decode(l.type,'TM','TABLE LOCK',           ...

  6. [入门帮助] Kafka入门经典教程

    问题导读 1.Kafka独特设计在什么地方?2.Kafka如何搭建及创建topic.发送消息.消费消息?3.如何书写Kafka程序?4.数据传输的事务定义有哪三种?5.Kafka判断一个节点是否活着有 ...

  7. html表格合并单元格

    th标签 合并列 colspan="k" 合并行 rowspan="k"   例子<th colspan="2", rowspan=& ...

  8. poj 3613 Cow Relays【矩阵快速幂+Floyd】

    !:自环也算一条路径 矩阵快速幂,把矩阵乘法的部分替换成Floyd(只用一个点扩张),这样每"乘"一次,就是经过增加一条边的最短路,用矩阵快速幂优化,然后因为边数是100级别的,所 ...

  9. Django day 34 过滤课程,登录,redis,python操作redis

    一:过滤课程, 二:登录 三:redis, 四:python操作redis

  10. 源码阅读之LinkedList(JDK8)

    inkedList概述 LinkedList是List和Deque接口的双向链表的实现.实现了所有可选列表操作,并允许包括null值. LinkedList既然是通过双向链表去实现的,那么它可以被当作 ...