题目

给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

最新文章

  1. [HIMCM暑期班]第3课:一个博弈问题
  2. Leetcode 102 Binary Tree Level Order Traversal 二叉树+BFS
  3. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试
  4. 第十一章 TClientDataSet
  5. 通过命令行连接oracle数据库/进入sql plus
  6. Git如何Check Out出指定文件或者文件夹
  7. two sets of Qt binaries into the same process的解决办法
  8. java程序员常见面试题目
  9. 2018年10月OKR初步规划
  10. 微信小程序--家庭记账本开发--06
  11. Holer实现外网访问本地MySQL数据库
  12. data science学习笔记1
  13. thyemleaf:禁用JS缓存(原创)
  14. vue 2.0 使用replace时要点击路由多次才能返回
  15. PAT 乙级 1026 程序运行时间(15) C++版
  16. Git 安装和使用教程(更加详细)
  17. Excel:公式应用技巧汇总
  18. IIS7增加mine类型,以便可以访问apk
  19. android 通过命令行启动Apk
  20. ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed

热门文章

  1. war,jar包是啥
  2. C#基础:线程之异步回调(委托)
  3. 201621123016《Java程序设计》第1周学习总结
  4. 聊聊IT行业加班的问题
  5. Codevs 1247 排排站
  6. 浅谈Nginx服务器的内部核心架构设计
  7. Pycharm2019.1.2永久激活
  8. 未知宽高div水平垂直居中的3种方法
  9. 可视化-grafana_使用influxDB数据
  10. JDBC事务之理论篇