zoukankan      html  css  js  c++  java
  • UVa 1599 Ideal Path (两次BFS)

    题意:给出n个点,m条边的无向图,每条边有一种颜色,求从结点1到结点n颜色字典序最小的最短路径。

    析:首先这是一个最短路径问题,应该是BFS,因为要保证是路径最短,还要考虑字典序,感觉挺麻烦的,并不好做,事实用两次BFS,

    第一次是倒序BFS,目的是得到从结点 i 到结点n的最短距离,然后再从第一个点开始到最后一个,要保证在查找时,每经过一点要让d值恰好减少1,

    直到终点,这也是一个BFS,因为这个字典序在某个结点是一样的,所以是两个BFS,我超时了好几次,因为少写了一个vis, 一定要细心,

    据说可以只用一次BFS,倒序,如果有兴趣可以尝试,反正我暂时没想出来,毕竟倒着字典序不好找.

    再就是这个图不好构造,不能用二维数组,我用一个vector来存在,用了2*n个长度,偶数下标存结点,奇数存颜色,遍历时要注意是+2, 不是++.

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cstring>
    
    using namespace std;
    const int maxn = 200000 + 5;
    const int INF = 0x3f3f3f3f;
    int d[maxn], vis[maxn], ans[maxn];
    vector<int> v[maxn];
    int Min(int a, int b){  return a < b ? a : b;  }
    
    void bfs1(int n){//逆序BFS
        memset(d, 0, sizeof(d));
        queue<int> q;
        memset(vis, 0, sizeof(vis));
        q.push(n);
        vis[n] = 1;
    
        while(!q.empty()){
            int u = q.front();  q.pop();
            for(int i = 0; i < v[u].size(); i += 2){
                int t = v[u][i];
                if(t == 1){  d[1] = d[u] + 1;  return;  }//小优化,找到1就行了
                if(vis[t])continue;
                d[t] = d[u] + 1;
                vis[t] = 1;
                q.push(t);
            }
        }
    }
    
    void bfs2(int n){
        memset(vis, 0, sizeof(vis));
        queue<int> q;
        q.push(n);
        vis[n] = 1;
        fill(ans, ans+d[1]+1, INF);
    
        while(!q.empty()){
            int u = q.front();     q.pop();
            if(!d[u])  return ;
            int m = INF;
            for(int i = 1; i < v[u].size(); i += 2)
                if(d[u] == d[v[u][i-1]]+1)   m = Min(m, v[u][i]);
    
            ans[d[1]-d[u]] = Min(ans[d[1]-d[u]], m);
            for(int i = 0; i < v[u].size(); i += 2)
                if(!vis[v[u][i]] && d[u] == d[v[u][i]]+1 && v[u][i+1] == m){
                    vis[v[u][i]] = 1;
                    q.push(v[u][i]);
                }
        }
    }
    
    int main(){
    //    freopen("in.txt", "r", stdin);
        int n, m;
        while(scanf("%d %d", &n, &m) == 2){
            for(int i = 1; i <= n; ++i)  v[i].clear();
            int x, y, w;
            for(int i = 0; i < m; ++i){
                scanf("%d %d %d", &x, &y, &w);
                v[x].push_back(y);
                v[x].push_back(w);
                v[y].push_back(x);
                v[y].push_back(w);
            }
    
            bfs1(n);
            bfs2(1);
            printf("%d
    ", d[1]);
            for(int i = 0; i < d[1]; ++i)
                if(!i)  printf("%d", ans[i]);
                else printf(" %d", ans[i]);
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    Symfony Component HttpKernel Exception AccessDeniedHttpException This action is unauthorized.
    AngularJs ng-repeat中使用ng-model
    JS数组排序sort()方法同时按照两种方式排序的用法
    MongoDB
    Node基本学习
    小程序 五 组件使用
    小程序 四 事件类型
    小程序 二 template模板(代码复用)
    小程序 wxs 脚本语言(2种使用方式)
    小程序初体验 wx:for
  • 原文地址:https://www.cnblogs.com/dwtfukgv/p/5595471.html
Copyright © 2011-2022 走看看