zoukankan      html  css  js  c++  java
  • POJ 3255 Roadblocks

    POJ_3255

        本来想做POJ_2449的,结果自己想的这个算法TLE,看来解决那个题只能搞A*了。

        这个题目由于求次短路,第K短路的K就是2,比较小,所以可以直接用纯dij搞。我的思路就是把图上每个点搞一个容量不小于K的最大堆和最小堆,最小堆用于取到达当前该节点的第某短路值,最大堆用来保存前K小的最短路。

        最后为了每次能查询全局最小值,再把N个点放到一个线段树(最小堆)上即可,剩下的工作就是进行dij的过程了,当访问终点的次数达到第K次时break即可,这时就是第K短路的值了。

        当然,这么做其实是麻烦了,因为实际上K为2,所以可以直接把一个点拆成两个点,一个存当前最短路值,一个存次短路值即可。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 5010
    #define MAXM 200010
    #define MAXT 5
    #define INF 0x3f3f3f3f
    int DI, DO, N, M, K, S, T, first[MAXD], next[MAXM], v[MAXM], w[MAXM], tree[4 * MAXD], e;
    struct Tree
    {
    int min, min_tree[MAXT], max_tree[MAXT], a[MAXT];
    void init()
    {
    int i;
    min = INF;
    for(i = 0; i < DI; i ++)
    {
    min_tree[i + DI] = max_tree[i + DI] = i;
    a[i] = INF;
    }
    for(i = DI - 1; i > 0; i --)
    {
    min_tree[i] = min_tree[i << 1];
    max_tree[i] = max_tree[i << 1];
    }
    }
    void update_min(int i)
    {
    for(; i ^ 1; i >>= 1)
    min_tree[i >> 1] = a[min_tree[i]] < a[min_tree[i ^ 1]] ? min_tree[i] : min_tree[i ^ 1];
    }
    void update_max(int i)
    {
    for(; i ^ 1; i >>= 1)
    max_tree[i >> 1] = a[max_tree[i]] > a[max_tree[i ^ 1]] ? max_tree[i] : max_tree[i ^ 1];
    }
    int Insert(int x)
    {
    int k = max_tree[1];
    if(x < a[k])
    {
    a[k] = x, update_max(DI + k), update_min(DI + k);
    if(x < min)
    {
    min = x;
    return 1;
    }
    }
    return 0;
    }
    void Delete()
    {
    int k = min_tree[1];
    a[k] = INF, update_min(DI + k);
    min = a[min_tree[1]];
    }
    }t[2 * MAXD];
    void add(int x, int y, int z)
    {
    w[e] = z, v[e] = y;
    next[e] = first[x], first[x] = e;
    ++ e;
    }
    void init()
    {
    int i, j, k, x, y, z;
    for(DO = 1; DO <= N; DO <<= 1);
    memset(first + 1, -1, sizeof(first[0]) * N);
    e = 0;
    for(i = 0; i < M; i ++)
    {
    scanf("%d%d%d", &x, &y, &z);
    add(x, y, z), add(y, x, z);
    }
    S = 1, T = N, K = 2;
    for(DI = 1; DI < K; DI <<= 1);
    }
    void update(int i)
    {
    for(; i ^ 1; i >>= 1)
    tree[i >> 1] = t[tree[i]].min < t[tree[i ^ 1]].min ? tree[i] : tree[i ^ 1];
    }
    void solve()
    {
    int i, j, k, cnt, x, y, z;
    memset(tree + 1, 0, sizeof(tree[0]) * (DO << 1));
    for(i = 0; i < DO; i ++)
    {
    t[i].init();
    tree[i + DO] = i;
    }
    for(i = DO - 1; i > 0; i --)
    tree[i] = tree[i << 1];
    t[S].Insert(0), update(S + DO);
    cnt = 0;
    while(t[x = tree[1]].min != INF)
    {
    if(x == T)
    {
    if(++ cnt == K)
    break;
    }
    for(i = first[x]; i != -1; i = next[i])
    if(t[v[i]].Insert(t[x].min + w[i]))
    update(v[i] + DO);
    t[x].Delete(), update(x + DO);
    }
    if(cnt == K)
    printf("%d\n", t[tree[1]].min);
    else
    printf("-1\n");
    }
    int main()
    {
    while(scanf("%d%d", &N, &M) == 2)
    {
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/staginner/p/2422545.html
Copyright © 2011-2022 走看看