UVa 1599 理想路径(反向BFS 求最短路径 )

题意:

给定一个有重边有自环的无向图,n个点(2 <= n <= 100000), m条边(1 <= m <= 200000), 每条边有一个权值, 求从第一个点到n的最少步数, 如果最少步数相同有多条路径, 那么输出权值字典序最小的一条。

分析:

用BFS解决最短路问题, 可以先从终点BFS, 求出每个点到终点的最短距离。 那么最少步数就是起点的最短距离, 最短路径就是从起点每次向最短距离比自己少1的顶点移动(如果有多个则可以随便走), 这样就可以保证走的是最短路径, 如果一开始我们是从起点BFS, 那么这样则不能保证走的是通往终点的最短路径。然后我们就可以从起点出发, 循环最短距离次, 每次选择字典序最少的走,  如果有多个字典序相同则选择多个, 直到走完最短距离, 就可以得出答案。 注意两次BFS都需要添加标记, 不然重边很可能就会导致TLE。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const int maxm = 1e7;
  4 const int maxn = 1e6 + 7;
  5 const int inf = 1e9;
  6 struct Node{
  7     int v,col,next;
  8     Node():v(0),col(0),next(0){}
  9 };
 10 struct ele{
 11     int v;
 12     int dist;
 13     ele(int v, int dist):v(v),dist(dist){}
 14 };
 15
 16 Node edge[maxn];
 17 int G[maxn], d[maxn];
 18 bool vis[maxn];
 19 int n, m, cnt;
 20
 21 void build(){
 22     memset(G,-1,sizeof(G));
 23         cnt = 0;
 24         for(int i = 0; i < m; i++){
 25             int u, v, col;
 26             scanf("%d %d %d", &u, &v, &col);
 27             if(u == v) continue;
 28             edge[cnt].v = v;
 29             edge[cnt].col = col;
 30             edge[cnt].next = G[u];
 31             G[u] = cnt++;
 32             edge[cnt].v = u;
 33             edge[cnt].col = col;
 34             edge[cnt].next = G[v];
 35             G[v] = cnt++;
 36         }
 37 }
 38
 39 void revbfs(){
 40     fill(d,d+maxn, inf);
 41     memset(vis,0,sizeof(vis));
 42     queue<ele> q;
 43     q.push(ele(n,0));
 44     d[n] = 0;
 45     vis[n] = 1;
 46     while(!q.empty()){
 47         ele u = q.front(); q.pop();
 48         d[u.v] = u.dist;
 49         for(int i = G[u.v]; i != -1; i = edge[i].next){
 50             int v = edge[i].v;
 51             if(d[v] < u.dist + 1 || vis[v]){
 52                 continue;
 53             }
 54             q.push(ele(v,u.dist+1));
 55             vis[v] = 1;
 56         }
 57     }
 58 }
 59 void bfs(){
 60     vector<int> path;
 61         memset(vis,0,sizeof(vis));
 62         vis[1] = 1;
 63         vector<int> next;
 64         next.push_back(1);
 65         for(int i = 0; i < d[1]; i++){//the essential minimum step
 66             int min_col = inf;
 67             for(int j = 0; j < next.size(); j++){
 68                 int u = next[j];
 69                 for(int k = G[u]; k != -1; k = edge[k].next){
 70                     int v = edge[k].v;
 71                     if(d[u] == d[v] + 1)
 72                         min_col = min(min_col,edge[k].col);
 73                 }
 74             }
 75             //find out the minimum color
 76             path.push_back(min_col);
 77
 78             vector<int> next2;
 79             for(int j = 0; j < next.size(); j++){
 80                 int u = next[j];
 81                 for(int k = G[u]; k != -1; k= edge[k].next){
 82                     int v = edge[k].v;
 83                     if(d[u] == d[v] + 1 && !vis[v] && edge[k].col == min_col){
 84                         vis[v] = 1;
 85                         next2.push_back(v);
 86                     }
 87                 }
 88             }
 89             next = next2;
 90         }
 91
 92
 93         printf("%d\n%d",(int)path.size(),path[0]);
 94         for(int i = 1; i < path.size(); i++){
 95             printf(" %d",path[i]);
 96         }
 97         puts("");
 98 }
 99 int main(){
100     freopen("1.txt","r",stdin);
101     while(~scanf("%d %d", &n, &m)){
102         build();
103         revbfs();//反向bfs求出终点到每个点的最短距离
104         bfs();
105     }
106      printf("%.3f",(double)clock()/CLOCKS_PER_SEC);
107     return 0;
108 }
时间: 2024-10-09 01:13:59

UVa 1599 理想路径(反向BFS 求最短路径 )的相关文章

UVA 816 -- Abbott&#39;s Revenge(BFS求最短路)

 UVA 816 -- Abbott's Revenge(BFS求最短路) 有一个 9 * 9 的交叉点的迷宫. 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可).进入一个交叉点的方向(用NEWS表示不同方向)不同时, 允许出去的方向也不相同. 例如:1 2 WLF NR ER * 表示如果 进去时朝W(左), 可以 左转(L)或直行(F), 如果 朝N只能右转(R) 如果朝E也只能右转.* 表示这个点的描述结束啦! 输入有: 起点的坐标, 朝向, 终点的坐标.然后是各个

UVa 1599 Ideal Path【BFS】

题意:给出n个点,m条边,每条边上涂有一个颜色,求从节点1到节点n的最短路径,如果最短路径有多条,要求经过的边上的颜色的字典序最小 紫书的思路:第一次从终点bfs,求出各个节点到终点的最短距离, 第二次bfs从起点沿着每到达一个节点d[]减少1来走,按照颜色的字典序最小的路径来走 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include&

Uva 1599 最佳路径

题目链接:https://uva.onlinejudge.org/external/15/1599.pdf 题意: 保证在最短路的时候,输出字典序最小的路径. 方法: 路径上有了权值,可以利用图论的数据结构来BFS,很方便. 逆序BFS,找到每个点距离终点的最短路长 d[x] ; 然后,从起点,沿着 d[u] = d[v] + 1; 的路径,分层BFS,选字典序最小的.找到那个最小字典序的节点之后,从新建队列.直到找完 d[0]; #include <bits/stdc++.h> using

bfs求最短路径

好久没写搜索,到忘了,找了半个小时错误. 一开始又把题看错了,真服自己了.(认真审题) 这题可以用excel写.but作为一个程序园,那就要使用灵魂操作. 核心算法:bfs层次遍历 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 string s[35]; 5 int vist[35][55];//标记 6 int disx[4] = {0, 0, -1, 1}; 7 int disy[4] = {1, -1, 0, 0}; 8 in

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

https://vjudge.net/problem/UVA-1599 给一个n个点m条边(2<=n<=100000,1<=m<=200000)的无向图,每条边上都涂有一种颜色.求从结点1到结点n的一条路径,使得经过的边数尽量少,在此前提下,经过边的颜色序列的字典序最小.一对结点可能有多条边,一条边可能连接相同的结点(自环).输入保证结点1可以到达结点n.颜色是1~10^9的整数. 分析: 从题目中我们可以看出,题目中的无向图是可以出现自环和重边的,自环我们可以在输入的时候检查并排

bfs:求最短路径的长度

*/--> pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;} pre.src {background-color: Black; color: White;}

Catch That Cow BFS求线性双向最短路径

Catch That Cow Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer

数据结构:可以用求最短路径的方法思想求最长路径么?给出详细解答。。

数据结构:可以用求最短路径的方法思想求最长路径么?为什么呢? 这里求解最短路径的通用方法有Dijkstra算法和Floyd-Warshall算法,Dijkstra算法不允许边的权值为负,也不允许有回路,而Floyd-Warshall算法可以允许边的权值为负,但不允许负值边构成回路,即可以求解有回路的图 它们都有局限,这两种算法的思想可以用来求最长路径么?? 为什么 不可以? (感谢给我答案的好心人:来自于知乎:http://www.zhihu.com/question/27201255和CSDN

逆向+两次bfs(UVA 1599)

为什么都说简单好想咧.坦白从宽看了人家的代码,涨了好多姿势,, http://blog.csdn.net/u013382399/article/details/38227917 被一个细节坑了.. 2147483647是0x7fffffff啊啊啊,7个f!!! 1 #include <iostream> 2 #include <sstream> 3 #include <cstdio> 4 #include <cstring> 5 #include <c