题目

给n个点m条边(2 ≤ n ≤ 100000,1 ≤ m ≤ 200000)的无向图,每条边上都涂有一种颜色。求从结点1到结点n的一条路径,使得经过的边数尽量的少,在此前提下,经过边的颜色序列的字典序最小。一对结点间可能有多条边,一条边可能连接两个相同的结点。输入保证结点1可以到达结点n。颜色为1~109的整数。

解题思路

方法是从终点开始倒着BFS,得到每个结点 i 到终点的最短距离d[i]。然后直接从起点开始走,但是每次到达一个新结点时要保证d值恰好减少1,直到到达终点,这样得到的一定是一条最短路。

有了上述结论,可以这样解决:直接从起点开始按照上述规则走,如果有多种走法,选择颜色字典序最小的走;如果有多条边的颜色字典序都最小,则记录所有这些边的终点,走下一步时要考虑从所有这些点出发的边。这实际上是又做了一次BFS,因此时间复杂度仍为 O(m)。

代码实现

 #include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
using namespace std; const int maxn = + ;
vector<int>G[maxn];
vector<int>C[maxn];
int n, m,vis[maxn], d[maxn], ans[maxn]; //d保存距离,ans保存最小距离 void init()
{
int x, y;
int tmp;
memset(vis, , sizeof(vis));
memset(d, , sizeof(d));
memset(ans, , sizeof(ans));
for (int i = ; i <=n; i++) G[i].clear();
for (int i = ; i <= n; i++) C[i].clear();
for (int i = ; i < m; i++)
{
cin >> x >> y;
G[x].push_back(y); G[y].push_back(x);
cin >> tmp;
C[x].push_back(tmp); C[y].push_back(tmp);
}
} void bfs1() //进行距离的遍历,得到d数组
{
memset(d, -, sizeof(d));
queue<int>q;
d[n] = ;
q.push(n);
while (!q.empty())
{
int u = q.front(); q.pop();
int sz = G[u].size();
for (int i = ; i < sz; i++)
{
int v = G[u][i];
if (d[v] == -)
{
d[v] = d[u] + ;
q.push(v);
}
}
}
return;
} void bfs2() //对颜色进行排序,并保存颜色
{
memset(vis, , sizeof(vis));
queue<int>q;
q.push();
while (!q.empty())
{
int u = q.front(); q.pop();
if (d[u] == ) return;
int sz = G[u].size();
int mm = -;
for (int i = ; i < sz; i++)
{
int v = G[u][i];
if (d[v] == d[u] - )
{
if (mm == -) mm = C[u][i];
else mm = min(mm, C[u][i]);
}
}
int t = d[] - d[u];
if (ans[t] == ) ans[t] = mm;
else ans[t] = min(ans[t], mm); for (int i = ; i < sz; i++) //将所有同时满足条件的节点加入队列,并同时进行bfs
{
int v = G[u][i];
if (vis[v] == false && d[v] == d[u] - && C[u][i] == mm)
{
q.push(v);
vis[v] = true;
}
}
}
return;
} int main()
{
while (scanf("%d%d",&n,&m) == )
{
init();
bfs1();
bfs2();
printf("%d\n", d[]);
for (int i = ; i < d[]; i++)
{
if (i) printf(" ");
printf("%d", ans[i]);
}
printf("\n");
}
return ;
}

参考链接:https://blog.csdn.net/cfarmerreally/article/details/52128440

理想路径——双向BFS的更多相关文章

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

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

  2. POJ 3170 Knights of Ni (暴力,双向BFS)

    题意:一个人要从2先走到4再走到3,计算最少路径. 析:其实这个题很水的,就是要注意,在没有到4之前是不能经过3的,一点要注意.其他的就比较简单了,就是一个双向BFS,先从2搜到4,再从3到搜到4, ...

  3. BFS、双向BFS和A*

    BFS.双向BFS和A* Table of Contents 1. BFS 2. 双向BFS 3. A*算法 光说不练是无用的.我们从广为人知的POJ 2243这道题谈起:题目大意:给定一个起点和一个 ...

  4. UVA1601-The Morning after Halloween(双向BFS)

    Problem UVA1601-The Morning after Halloween Accept: 289 Submit: 3136 Time Limit: 12000 mSec  Problem ...

  5. Eight (HDU - 1043|POJ - 1077)(A* | 双向bfs+康拓展开)

    The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've see ...

  6. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  7. BFS:HDU2612-Find a way(双向BFS)

    Find a way Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. POJ1077 Eight —— 双向BFS

    主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html (代码一直在精简完善……) 代码一:两个BFS, 两段代码: 用step控制“你一步, 我一步 ...

  9. Nightmare Ⅱ(双向BFS)

    Problem Description Last night, little erriyue had a horrible nightmare. He dreamed that he and his ...

随机推荐

  1. Identity Server 4 原理和实战(完结)_Hybrid Flow 实例, Claims, 角色授权和策略授权

    4分50 建立客户端 不需要身份认证 客户端叫做HybirdClient 配置IdentityServer服务端,先把客户端添加上 把userClaims添加到token里面 然后运行服务端就可以了 ...

  2. CCF 201509-1 数列分段 (水题)

    问题描述 给定一个整数数列,数列中连续相同的最长整数序列算成一段,问数列中共有多少段? 输入格式 输入的第一行包含一个整数n,表示数列中整数的个数. 第二行包含n个整数a1, a2, …, an,表示 ...

  3. HDU - 1241 POJ - 1562 Oil Deposits DFS FloodFill漫水填充法求连通块问题

    Oil Deposits The GeoSurvComp geologic survey company is responsible for detecting underground oil de ...

  4. c#重写 重载

    重写:当一个子类继承一父类,而子类中的方法与父类中的方法的名称,参数个数.类型都完全一致时,就称子类中的这个方法重写了父类中的方法. 重写:通常,派生类继承基类的方法.因此,在调用对象继承方法的时候, ...

  5. lua面向对象实现(实例化对象、继承、多态、多继承、单例模式)

    lua面向对象实现: 一个类就像是一个创建对象的模具.有些面向对象语言提供了类的概念,在这些语言中每个对象都是某个特定类的实例.lua则没有类的概念,每个对象只能自定义行为和形态.不过,要在lua中模 ...

  6. Linux环境下Nginx及负载均衡

    Nginx 简介 Nginx 是一个高性能的 HTTP 和反向代理 Web 服务器,同时也提供了 IMAP/POP3/SMTP 服务.前向代理作为客户端的代理,服务端只知道代理的 IP 地址而不知道客 ...

  7. django框架知识3

    1.Django安装: 1.安装版本Django1.11.11 2.安装方式:命令行安装   pycharm安装 2.创建Django项目 1.创建方式:cd到你要创建的目录下  然后输入 Djang ...

  8. SpringBoot 2.0 整合sharding-jdbc中间件,实现数据分库分表

    一.水平分割 1.水平分库 1).概念: 以字段为依据,按照一定策略,将一个库中的数据拆分到多个库中. 2).结果 每个库的结构都一样:数据都不一样: 所有库的并集是全量数据: 2.水平分表 1).概 ...

  9. POI刷题记录

    POI2007 HNOI2018滚粗后,默默来刷POI 先从2007刷起 bzoj1103[POI2007]大都市meg bzoj1098[POI2007]办公楼biu bzoj1102[POI200 ...

  10. ZOJ 4019 Schrödinger's Knapsack (from The 18th Zhejiang University Programming Contest Sponsored by TuSimple)

    题意: 第一类物品的价值为k1,第二类物品价值为k2,背包的体积是 c ,第一类物品有n 个,每个体积为S11,S12,S13,S14.....S1n ; 第二类物品有 m 个,每个体积为 S21,S ...