• POJ 3463 Sightseeing


    POJ_3463

        题目要求去求最短路以及比最短路大1的所有路径的数量。

        如果单求最短路数量的话,我们可以直接用SPFA+dp或者dij+dp去做,而这个题目不过是多了一个相当于次短路的数量的问题,因此我们可以把每个点拆成两个点,一个点记录最短路的距离及路径数量,另一个记录次短路距离及路径数量,用dij+dp去处理应该更方便一些。

        每次更新时,如果比最短路小,就把次短路的相关数据先更新成之前的最短路的数据,然后再更新最短路的数据,如果比最短路大但比次短路小就只需更新次短路的数据,其他的一些情况就比较好分析了。

    #include<stdio.h>
    #include<string.h>
    #define MAXD 1010
    #define MAXM 10010
    #define INF 0x3f3f3f3f
    int N, M, D, S, T, e, first[MAXD], next[MAXM], v[MAXM], w[MAXM], tree[8 * MAXD], d[2 * MAXD], ans[2 * MAXD];
    void init()
    {
    int i, j, k, x, y, z;
    e = 0;
    scanf("%d%d", &N, &M);
    memset(first + 1, -1, sizeof(first[0]) * N);
    for(i = 0; i < M; i ++)
    {
    scanf("%d%d%d", &x, &y, &z);
    v[e] = y, w[e] = z;
    next[e] = first[x];
    first[x] = e;
    ++ e;
    }
    }
    void update(int i)
    {
    for(; i ^ 1; i >>= 1)
    tree[i >> 1] = d[tree[i]] < d[tree[i ^ 1]] ? tree[i] : tree[i ^ 1];
    }
    void solve()
    {
    int i, j, k, x, y1, y2;
    for(D = 1; D < 2 * N + 4; D <<= 1);
    memset(d, 0x3f, sizeof(d));
    memset(tree, 0, sizeof(tree));
    for(i = 2; i <= 2 * N + 1; i ++)
    tree[D + i] = i;
    scanf("%d%d", &S, &T);
    d[S << 1] = 0;
    ans[S << 1] = 1;
    update(D + (S << 1));
    while(d[tree[1]] != INF)
    {
    x = tree[1];
    if(x == ((T << 1) ^ 1))
    break;
    for(i = first[x >> 1]; i != -1; i = next[i])
    {
    y1 = v[i] << 1, y2 = (v[i] << 1) ^ 1;
    if(d[x] + w[i] <= d[y1])
    {
    if(d[x] + w[i] < d[y1])
    {
    d[y2] = d[y1], ans[y2] = ans[y1];
    update(D + y2);
    d[y1] = d[x] + w[i], ans[y1] = ans[x];
    update(D + y1);
    }
    else
    ans[y1] += ans[x];
    }
    else if(d[x] + w[i] <= d[y2])
    {
    if(d[x] + w[i] < d[y2])
    {
    d[y2] = d[x] + w[i], ans[y2] = ans[x];
    update(D + y2);
    }
    else
    ans[y2] += ans[x];
    }
    }
    tree[x + D] = 0;
    update(x + D);
    }
    printf("%d\n", ans[T << 1] + (d[(T << 1) ^ 1] == d[T << 1] + 1 ? ans[(T << 1) ^ 1] : 0));
    }
    int main()
    {
    int t;
    scanf("%d", &t);
    while(t --)
    {
    init();
    solve();
    }
    return 0;
    }


  • 相关阅读:
    一类分治问题
    [POI2005]DWU-Double-row
    [SCOI2007]降雨量
    [POI2007]ODW-Weights(贪心)
    bzoj3427小P的牧场(斜率优化dp)
    UVA10559 Blocks(区间dp)
    LOJ6089 小Y的背包计数问题(根号优化背包)
    [APIO2008]免费道路(生成树)
    bzoj4383(拓扑排序)
    [HEOI2014]平衡(整数划分数)
  • 原文地址:https://www.cnblogs.com/staginner/p/2404226.html
Copyright © 2020-2023  润新知