UVa 1599 - Ideal Path <两次BFS>
两个月前就搞这道题,昨天翻出来直接修改的当时的超时代码,经历了多种错误,最后终于还是AC了。
这道题还是挺好的一道题,需要正反两次BFS,需要加各种防超时的判断。实际上还是考差对问题的理解,什么时候应该剪枝,什么地方不必重复判断。
第一次反着BFS,找到各点到终点的最短距离。第二次正着BFS,顺着距离递减的方向,按照颜色小的优先的方法走。
#include <cstdio> #include <cstdlib> #include <cstring> #include <vector> #include <climits> #include <queue> #define MAXN 102400 using namespace std; int n, m; vector<int> road[MAXN], col[MAXN]; int d[MAXN], ans[MAXN]; bool vis[MAXN]; void clr() { for(int i = 0; i < MAXN; i++) road[i].clear(), col[i].clear(); memset(d, -1, sizeof(d)); memset(ans, 0, sizeof(ans)); memset(vis, false, sizeof(vis)); } void BFS1() { queue<int> qu; qu.push(n); d[n] = 0; while(!qu.empty()){ int u = qu.front(); qu.pop(); for(size_t i = 0; i != road[u].size(); i++) if(d[road[u][i]]==-1){ int v = road[u][i]; d[v] = d[u] + 1; if(v == 1) return; qu.push(v); } } } void BFS2() { queue<int> qu; qu.push(1); while(!qu.empty()){ int u = qu.front(); qu.pop(); if(u==n) return; int curd = d[u]; int minclr = INT_MAX; for(size_t i = 0, sz = road[u].size(); i < sz; ++i) if(d[road[u][i]] + 1 == curd) minclr = min(minclr, col[u][i]); if(!ans[curd] || minclr<=ans[curd]) ans[curd] = minclr; else continue; for(size_t i = 0, sz = road[u].size(); i < sz; ++i){ int v = road[u][i]; if(!vis[v] && col[u][i]==minclr && d[v]+1==curd) qu.push(v), vis[v] = true; } } } int main() { //freopen("in.txt", "r", stdin); while(clr(), ~scanf("%d %d", &n, &m)){ while(m--){ int a, b, c; scanf("%d %d %d", &a, &b, &c); road[a].push_back(b); col[a].push_back(c); road[b].push_back(a); col[b].push_back(c); } BFS1(); BFS2(); printf("%d\n", d[1]); for(int i = d[1]; i >= 1; --i){ if(i==d[1]) printf("%d", ans[i]); else printf(" %d", ans[i]); } printf("\n"); } return 0; }