Uva 1599 Ideal Path - 双向BFS
题目大意:
对于一个n个房间m条路径的迷宫(Labyrinth)(2<=n<=100000, 1<=m<=200000),每条路径上都涂有颜色,颜色取值范围为1<=c<=10^9。求从节点1到节点n的一条路径,使得经过的边尽量少,在这样的前提下,如果有多条路径边数均为最小,则颜色的字典序最小的路径获胜。一条路径可能连接两个相同的房间,一对房间之间可能有多条路径。输入保证可以从节点1到达节点n。
这题思路很简单但还真没少折腾,前后修改提交了七八次才AC...(也说明自己有多菜了)..
注意问题:
1.看清楚原题的输入输出要求,刚了书上的中文题目直接开撸,以为输入输出都是只有一个情况的,所以一开始没加循环导致了WA
2. bfs要解决重复入队问题,在bfs1中由于一开始的方法导致重复入队,提交后TLE
3. 将d数组初始化为一个较大的整数 INF = 0x5ffffff ,然后找最小颜色的时候比INF小就修改,提交后WA,原因可能为测试数据中存在颜色号码真的为INF的数据,改为用-1充当INF
总结:
1.要看清楚原题的输入输出要求
2.bfs重复入队问题的解决方法
3.INF标识尽量用题目不可能出现的数据,如果数据都是正整数,可用-1
AC代码:
#include <iostream> #include <cstring> #include <vector> #include <queue> #include <stdio.h> #include <algorithm> #define maxn 100005 using namespace std; struct ver { int next,color; ver(int a,int b) : next(a),color(b) {} ver() {} }; vector<ver> G[maxn]; int vis[maxn]; int d[maxn]; int n,m; int res[maxn]; int inque[maxn]; void bfs1() { memset(d,-1,sizeof(d)); int u,t; queue<int> Q; d[n] = 0; Q.push(n); while(!Q.empty()) { t = Q.front(); Q.pop(); int sz = G[t].size(); for(int i =0; i < sz; ++i) { u = G[t][i].next; if(u == 1) { d[1] = d[t] + 1; return; } if(d[u] == -1) //未访问过 { d[u] = d[t] + 1; Q.push(u); } } } } void bfs2() { memset(res,0,sizeof(res)); memset(inque,0,sizeof(inque)); queue<int> Q; int end,clr,minc; int begin = 1; Q.push(begin); while(!Q.empty()) { begin = Q.front(); Q.pop(); if(begin == n) return; minc = -1; for(int i = 0; i< G[begin].size(); i++) //1st find min color { end = G[begin][i].next; clr = G[begin][i].color; if(d[end] == d[begin]-1) { if(minc == -1) minc = clr; else minc = min(minc,clr); } } int index = d[1] - d[begin]; //当前步长 if(res[index] == 0) res[index] = minc; else res[index] = min(res[index],minc); for(int j = 0; j < G[begin].size();j++) //2st go { end = G[begin][j].next; clr = G[begin][j].color; if(clr == minc && d[end] == d[begin]-1 && !inque[end]) { Q.push(end); inque[end] = 1; } } } } int main() { int a,b,c; while(scanf("%d %d",&n,&m) == 2) { for(int i = 0; i <= n; ++i) G[i].clear(); for(int i = 0; i < m; ++i) { scanf("%d %d %d",&a,&b,&c); if(a == b) continue; ver edge1(b,c); ver edge2(a,c); G[a].push_back(edge1); G[b].push_back(edge2); } bfs1(); bfs2(); printf("%d\n",d[1]); printf("%d",res[0]); for(int i = 1; i < d[1]; ++i) printf(" %d",res[i]); printf("\n"); } return 0; }