UVA 1599 Ideal Path(bfs1+bfs2,双向bfs)

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

第一次bfs逆向搜索,得到每个点到终点的最短距离,找出最短路;第二次bfs根据最短距离可以选择满足条件的最短路。

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<math.h>
  7 #include<algorithm>
  8 #include<queue>
  9 #include<set>
 10 #include<bitset>
 11 #include<map>
 12 #include<vector>
 13 #include<stdlib.h>
 14 #include <stack>
 15 using namespace std;
 16 int dirx[]={0,0,-1,1};
 17 int diry[]={-1,1,0,0};
 18 #define PI acos(-1.0)
 19 #define max(a,b) (a) > (b) ? (a) : (b)
 20 #define min(a,b) (a) < (b) ? (a) : (b)
 21 #define ll long long
 22 #define eps 1e-10
 23 #define MOD 1000000007
 24 #define N 100006
 25 #define inf 1e12
 26 int n,m;
 27 vector<int>G[N];
 28 vector<int>C[N];
 29 int dis[N];
 30 int vis[N];
 31 int ans[N];
 32 void bfs1(){//得到每一点到终点的最短距离的模板
 33     queue<int> q;
 34     q.push(n);
 35     dis[n]=0;
 36     while(!q.empty()){
 37         int u=q.front();
 38         q.pop();
 39
 40         for(int i=0;i<G[u].size();i++){
 41             int v=G[u][i];
 42             if(v==1){
 43                 dis[v]=dis[u]+1;
 44                 return;
 45             }
 46             if(dis[v]==-1){
 47                 dis[v]=dis[u]+1;
 48                 q.push(v);
 49             }
 50         }
 51     }
 52 }
 53 void bfs2(){
 54     queue<int> q;
 55     q.push(1);
 56     while(!q.empty()){
 57         int u=q.front();
 58         q.pop();
 59         if(dis[u]==0){
 60             return;
 61         }
 62         int minn=-1;
 63         for(int i=0;i<G[u].size();i++){
 64             int v=G[u][i];
 65             if(dis[v]==dis[u]-1){
 66                 if(minn==-1){
 67                     minn=C[u][i];
 68                 }
 69                 else{
 70                     minn=min(minn,C[u][i]);
 71                 }
 72             }
 73         }
 74
 75         int t=dis[1]-dis[u];
 76         if(ans[t]==0){
 77             ans[t]=minn;
 78         }
 79           else{
 80               ans[t]=min(ans[t],minn);
 81           }
 82
 83         for(int i=0;i<G[u].size();i++){
 84             int v=G[u][i];
 85
 86             if(vis[v]==0 && dis[v]==dis[u]-1 && C[u][i]==minn){
 87                 q.push(v);
 88                 vis[v]=1;
 89             }
 90         }
 91     }
 92 }
 93 int main()
 94 {
 95     while(scanf("%d%d",&n,&m)==2){
 96         for(int i=0;i<N;i++){
 97             G[i].clear();
 98             C[i].clear();
 99             dis[i]=-1;
100             vis[i]=0;
101             ans[i]=0;
102         }
103         for(int i=0;i<m;i++){
104             int x,y,c;
105             scanf("%d%d%d",&x,&y,&c);
106             G[x].push_back(y);
107             G[y].push_back(x);
108             C[x].push_back(c);//存 颜 色
109             C[y].push_back(c);
110         }
111         bfs1();//求 出 每 一 点 到 n 的 最 短 距 离
112         printf("%d\n",dis[1]);
113         bfs2();//从 1开始找最短的路径 ,以及字典序最小
114         for(int i=0;i<dis[1];i++){
115             if(i){
116                 printf(" ");
117             }
118             printf("%d",ans[i]);
119         }
120         printf("\n");
121     }
122     return 0;
123 } 

时间: 2024-08-03 11:47:30

UVA 1599 Ideal Path(bfs1+bfs2,双向bfs)的相关文章

UVa 1599 Ideal Path (两次BFS)

题意:给出n个点,m条边的无向图,每条边有一种颜色,求从结点1到结点n颜色字典序最小的最短路径. 析:首先这是一个最短路径问题,应该是BFS,因为要保证是路径最短,还要考虑字典序,感觉挺麻烦的,并不好做,事实用两次BFS, 第一次是倒序BFS,目的是得到从结点 i 到结点n的最短距离,然后再从第一个点开始到最后一个,要保证在查找时,每经过一点要让d值恰好减少1, 直到终点,这也是一个BFS,因为这个字典序在某个结点是一样的,所以是两个BFS,我超时了好几次,因为少写了一个vis, 一定要细心,

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的整数. 分析: 从题目中我们可以看出,题目中的无向图是可以出现自环和重边的,自环我们可以在输入的时候检查并排

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 Ideal Path

题意: 给出n和m,n代表有n个城市.接下来m行,分别给出a,b,c.代表a与b之间有一条颜色为c的道路.求最少走几条道路才能从1走到n.输出要走的道路数和颜色.保证颜色的字典序最小. 分析: bfs,先倒搜一次,求出每个点到终点的距离d[i].然后从起点走,每次走到新点保证d-1且颜色最小. 代码: #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #

逆向+两次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

Colour Hash (Uva 704 双向bfs)

Colour Hash Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description This puzzle consists of two wheels. Both wheels can rotate both clock and counter-clockwise. They contain 21 coloured pieces, 10 of which

UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS &amp;&amp; 降维 &amp;&amp; 状压)

题意 :w*h(w,h≤16)网格上有n(n≤3)个小写字母(代表鬼).要求把它们分别移动到对应的大写字母里.每步可以有多个鬼同时移动(均为往上下左右4个方向之一移动),但每步结束之后任何两个鬼不能占用同一个位置,也不能在一步之内交换位置.输入保证所有空格连通,所有障碍格也连通,且任何一个2*2子网格中至少有一个障碍格.输出最少的步数.输入保证有解. 分析 :可以将当前所有小鬼的位置作为一个状态,然后模拟小鬼移动BFS拓展出其他可行状态并且顺带记录步数,直到所有的小鬼都到达终点.首先状态如何表示

UVA 1601 双向BFS

但是我们还不是很清楚每一次的状态怎么储存?我们可以用一个结构体,将每次的位置存起来,但是这个程序中用了一个更好的储存方法:我们知道最大的格数是16*16个,也就是256个,那么我们转换为二进制表示就是8位数,那么我们可以使用24位的二进制表示啊!然后我们再进行解压缩,所以这就是很神奇的地方! 普通BFS #include<iostream> #include<string> #include<cmath> #include<cstring> #include

UVa1599,Ideal Path

说实话,这题参考的: http://blog.csdn.net/u013382399/article/details/38227917 倒着BFS就把我难住了T T,原来这样倒着BFS一遍,遍历完所有的点后就能得到每一点到终点的最短距离啊(其实做完反思后仔细想了想,发现其实当第一次bfs到首节点时,该图已经遍历完成了),一开始没转过这个弯来T T,我直接调用了N次dfs(i)囧rz.... 一开始我还想着吧color[]排序...这样更费时.....我写的dfs2()写着写着就乱了,本来思路还清