• POJ 1724 ROADS


    POJ_1724

        这个题目可以直接将SPFA中的dis[]变成二维的dis[i][k]表示到第i个点花费为k时的最短路,但如果直接做SPFA会超时,需要加一个剪枝:设mind[i]表示到第i个点的用于剪枝最短路,mink[i] 表示第i个点的用于剪枝的最小花费,如果在SPFA的过程中走到了第i个点的路径长为d花费为k,那么如果d>=mind[i]&&k>=mink[i],这时就进行剪枝,如果d<mind[i]&&k<mink[i]就更新mind[i]与mink[i]的值,并将这个点(i,k)入队,其余的情况也要将(i,k)入队。

        这个题目还可以用堆形式的SPFA去做,这时需要把N个点看成N*(K+1)个点,且堆顶的元素为当前所有点中dis[]的值最小的一个。其余的操作和SPFA大体相同,这时同样有一个剪枝:如果堆顶的元素是标号为N的点,那么就可以直接结束SPFA了。

    //普通的SPFA
    #include<stdio.h>
    #include<string.h>
    #define MAXD 110
    #define MAXK 10010
    #define MAXM 10010
    #define MAXQ 1000110
    #define INF 0x3f3f3f3f
    int N, M, K, first[MAXD], next[MAXM], v[MAXM], w[MAXM], cost[MAXM], e, q[MAXQ], m[MAXQ], inq[MAXD][MAXK], d[MAXD][MAXK], mind[MAXD], mink[MAXD], Q = 1000100;
    void add(int &x, int &y, int &z, int &t)
    {
    v[e] = y;
    w[e] = z;
    cost[e] = t;
    next[e] = first[x];
    first[x] = e;
    ++ e;
    }
    void init()
    {
    int i, j, k, x, y, z, t;
    e = 0;
    memset(first, -1, sizeof(first));
    scanf("%d%d", &N, &M);
    for(i = 0; i < M; i ++)
    {
    scanf("%d%d%d%d", &x, &y, &z, &t);
    add(x, y, z, t);
    }
    }
    void solve()
    {
    int i, j, k, x, y, z, newk, front ,rear, ans;
    front = rear = 0;
    for(i = 1; i <= N; i ++)
    for(j = 0; j <= K; j ++)
    d[i][j] = INF, inq[i][j] = 0;
    memset(mind, 0x3f, sizeof(mind));
    memset(mink, 0x3f, sizeof(mink));
    q[rear] = 1, m[rear] = 0, d[1][0] = 0;
    ++ rear;
    mind[1] = mink[1] = 0;
    while(front != rear)
    {
    x = q[front], k = m[front];
    inq[x][k] = 0;
    ++ front;
    if(front > Q)
    front = 0;
    for(i = first[x]; i != -1; i = next[i])
    {
    y = v[i], newk = k + cost[i], z= d[x][k] + w[i];
    if(newk <= K && z < d[y][newk])
    {
    if(z >= mind[y] && newk >= mink[y])
    continue;
    if(z < mind[y] && newk < mink[y])
    mind[y] = z, mink[y] = newk;
    d[y][newk] = z;
    if(!inq[y][newk])
    {
    q[rear] = y;
    m[rear] = newk;
    inq[y][newk] = 1;
    ++ rear;
    if(rear > Q)
    rear = 0;
    }
    }
    }
    }
    ans = INF;
    for(i = 0; i <= K; i ++)
    if(d[N][i] < ans)
    ans = d[N][i];
    printf("%d\n", ans == INF ? -1 : ans);
    }
    int main()
    {
    while(scanf("%d", &K) == 1)
    {
    init();
    solve();
    }
    return 0;
    }
    //堆形式的SPFA
    #include<stdio.h>
    #include<string.h>
    #define MAXD 110
    #define MAX 4000410
    #define MAXM 10010
    #define INF 0x3f3f3f3f
    int N, M, K, first[MAXD], next[MAXM], v[MAXM], w[MAXM], cost[MAXM], P, f[MAX], d[MAX], m[MAX], tree[MAX], mind[MAXD], mink[MAXD];
    void init()
    {
    int i, j, k, x, y, z, t;
    memset(first, -1, sizeof(first));
    scanf("%d%d", &N, &M);
    for(i = 0; i < M; i ++)
    {
    scanf("%d%d%d%d", &x, &y, &z, &t);
    v[i] = y;
    w[i] = z;
    cost[i] = t;
    next[i] = first[x];
    first[x] = i;
    }
    }
    void insert(int cur, int dis, int k)
    {
    int i, left, right, s = k * N + cur;
    if(dis < d[s])
    {
    f[s] = cur;
    d[s] = dis;
    m[s] = k;
    i = P + s;
    if(!tree[i])
    {
    tree[i] = s;
    for(i >>= 1; i > 0; i >>= 1)
    {
    left = tree[2 * i], right = tree[2 * i + 1];
    tree[i] = d[left] < d[right] ? left : right;
    }
    }
    }
    }
    void update()
    {
    int i, left, right, s = tree[1];
    i = P + s;
    tree[i] = 0;
    for(i >>= 1; i > 0; i >>= 1)
    {
    left = tree[2 * i], right = tree[2 * i + 1];
    tree[i] = d[left] < d[right] ? left : right;
    }
    }
    void solve()
    {
    int i, j, k, x, y, z, s, t, ans;
    memset(mind, 0x3f, sizeof(mind));
    memset(mink, 0x3f, sizeof(mink));
    for(P = 1; P < (K + 1) * N + 2; P <<= 1);
    for(i = (K + 1) * N; i >= 0; i --)
    d[i] = INF;
    for(i = 2 * P - 1; i > 0; i --)
    tree[i] = 0;
    d[0] = m[0] = INF;
    insert(1, 0, 0);
    mind[1] = mink[1] = 0;
    while(tree[1])
    {
    s = tree[1];
    if(s % N == 0)
    break;
    update();
    x = f[s], k = m[s];
    for(i = first[x]; i != -1; i = next[i])
    {
    y = v[i], z = d[s] + w[i], t = k + cost[i];
    if(t <= K)
    {
    if(z >= mind[y] && t >= mink[y])
    continue;
    if(z < mind[y] && t < mink[y])
    mind[y] = z, mink[y] = t;
    insert(y, z, t);
    }
    }
    }
    printf("%d\n", tree[1] ? d[s] : -1);
    }
    int main()
    {
    while(scanf("%d", &K) == 1)
    {
    init();
    solve();
    }
    return 0;
    }



  • 相关阅读:
    一些零碎小知识点积累随笔
    STM32学习笔记——新建工程模板步骤(向原子哥学习)
    记一次电信反射xss的挖掘与利用
    mysql字符串操作相关函数用法总结
    mysql学习笔记
    sigmoid function的直观解释
    多变量线性回归时使用梯度下降(Gradient Descent)求最小值的注意事项
    SAE中Python无法创建多线程的解决方案
    BCNF/3NF 数据库设计范式简介
    web.py下获取get参数
  • 原文地址:https://www.cnblogs.com/staginner/p/2332493.html
Copyright © 2020-2023  润新知