zoukankan      html  css  js  c++  java
  • BZOJ 2200 [Usaco2011 Jan]道路和航线

    BZOJ_2200

        这个题目一看就知道SPFA可做,但是SPFA就是超时……

        USACO上给出的解法的大致意思是:由于每条航线都是单向的,而且不存在从航线的终点辗转到航线起点的通路,那么就是说航线将原图分成了若干个相对封闭的区域,我们把航线从原图中拿掉后,剩下的就应当是若干个连通块。由于每个连通块中只有非负权边,那么我们就可以在连通块内用Dijkstra求最短路了。而且从S开始做最短路时,这些连通块是有一定的拓扑关系的,也就是说只有先确定了S到某些连通块中的点的最短路,才能确定S到另一些连通块中的点的最短路,这样按连通块的拓扑顺序,一个连通块一个连通块的不断地求最短路,就可以得到S到每个点的最短路了。

    #include<stdio.h>
    #include<string.h>
    #include<vector>
    #include<queue>
    #define MAXD 25010
    #define INF 0x3f3f3f3f
    struct Edge
    {
        int v, c;
        Edge(){}
        Edge(int _v, int _c) : v(_v), c(_c){}
    };
    std::vector<Edge> road[MAXD], fly[MAXD];
    int T, R, P, S;
    void init()
    {
        int x, y, c;
        for(int i = 1; i <= T; i ++) road[i].clear(), fly[i].clear();
        for(int i = 0; i < R; i ++)
        {
            scanf("%d%d%d", &x, &y, &c);
            road[x].push_back(Edge(y, c)), road[y].push_back(Edge(x, c));
    
        }
        for(int i = 0; i < P; i ++)
        {
            scanf("%d%d%d", &x, &y, &c);
            fly[x].push_back(Edge(y, c));
        }
    }
    int p[MAXD], dgr[MAXD], dis[MAXD], cal[MAXD];
    struct St
    {
        int id, v;
        St(){}
        St(int _id, int _v) : id(_id), v(_v){}
        bool operator < (const St &t) const
        {
            return v > t.v;
        }
    };
    int find(int x)
    {
        return p[x] == x ? x : (p[x] = find(p[x]));
    }
    void bfs()
    {
        memset(dgr, 0, sizeof(dgr[0]) * (T + 1));
        std::queue<int> q;
        memset(cal, 0, sizeof(cal[0]) * (T + 1));
        cal[S] = 1, q.push(S);
        while(!q.empty())
        {
            int x = q.front();
            q.pop();
            for(int i = 0; i < road[x].size(); i ++)
            {
                int y = road[x][i].v;
                if(!cal[y]) cal[y] = 1, q.push(y);
            }
            for(int i = 0; i < fly[x].size(); i ++)
            {
                int y = fly[x][i].v;
                ++ dgr[find(y)];
                if(!cal[y]) cal[y] = 1, q.push(y);
            }
        }
    }
    void dij(int set, std::queue<int> &wait, std::vector<int> ini[])
    {
        std::priority_queue<St> q;
        for(int i = 0; i < ini[set].size(); i ++)
        {
            int x = ini[set][i];
            q.push(St(x, dis[x]));
        }
        while(!q.empty())
        {
            St st = q.top();
            q.pop();
            int x = st.id;
            if(cal[x]) continue;
            cal[x] = 1;
            for(int i = 0; i < road[x].size(); i ++)
            {
                int y = road[x][i].v, c = road[x][i].c;
                if(dis[x] + c < dis[y]) dis[y] = dis[x] + c, q.push(St(y, dis[y]));
            }
            for(int i = 0; i < fly[x].size(); i ++)
            {
                int y = fly[x][i].v, c = fly[x][i].c, set = find(y);
                -- dgr[set];
                if(dgr[set] == 0) wait.push(set);
                if(dis[x] + c < dis[y]) dis[y] = dis[x] + c, ini[set].push_back(y);
            }
        }
    }
    void solve()
    {
        for(int i = 1; i <= T; i ++) p[i] = i;
        for(int i = 1; i <= T; i ++)
            for(int j = 0; j < road[i].size(); j ++)
            {
                int x = find(i), y = find(road[i][j].v);
                if(x != y) p[x] = y;
            }
        bfs();
        std::vector<int> ini[MAXD];
        std::queue<int> wait;
        memset(dis, 0x3f, sizeof(dis[0]) * (T + 1));
        dis[S] = 0, ini[find(S)].push_back(S), wait.push(find(S));
        memset(cal, 0, sizeof(cal[0]) * (T + 1));
        while(!wait.empty())
        {
            int set = wait.front();
            wait.pop();
            dij(set, wait, ini);
        }
        for(int i = 1; i <= T; i ++)
        {
            if(dis[i] == INF) printf("NO PATH\n");
            else printf("%d\n", dis[i]);
        }
    }
    int main()
    {
        while(scanf("%d%d%d%d", &T, &R, &P, &S) == 4)
        {
            init();
            solve();
        }
        return 0;
    }
  • 相关阅读:
    NSTimer与循环引用
    Swift类实例与循环引用的解决
    Swift运算符函数与自定义运算符
    Swift延迟存储属性
    Swift枚举-相关值与递归枚举
    互斥锁、自旋锁、dispatch_once性能对比
    Swift闭包与简化
    原子属性和使用互斥锁实现的属性的性能对比
    [HDOJ]_PID_1004_Let the Balloon Rise
    [HDOJ]_PID_2087_剪花布条
  • 原文地址:https://www.cnblogs.com/staginner/p/2709487.html
Copyright © 2011-2022 走看看