zoukankan      html  css  js  c++  java
  • POJ1722二维spfa+优先队列优化

    题意:
         给你一个有向图,然后求从起点到终点的最短,但是还有一个限制,就是总花费不能超过k,也就是说每条边上有两个权值,一个是长度,一个是花费,求满足花费的最短长度。


    思路:
          一开始写了一个mark[i][j]第i个点花费j状态的spfa,TLE了,然后又优化了下,就是先反向搜索一遍简单最短路(以花费为权值)然后用这个结果在mark[][]二维的最短路里面剪枝用,结果还是超时了,然后又尝试了下优先队列,结果900+ac险过,我把自己的第一个优化去掉,结果跑了800+,哎!对于在spfa上使用优先队列,这个我感觉还是不是很靠谱啊,如果不考虑优先队列的时间复杂度跑spfa确实是个优化,因为毕竟有点贪心的意思(具体能优化多少,要看数据,总之不会像记忆化搜索那样级别的优化就是了),可是优先队列的操作时间是log级别的,在他们两个之间去衡量,还是要看具体数据啊。


    这是个有反向搜索预处理优化的ac代码,把反向预处理去掉之后会更快一点(哎!)


    #include<queue>
    #include<stdio.h>
    #include<string.h>


    #define N_node 100 + 5
    #define N_edge 10000 + 10
    #define INF 100000000


    using namespace std;


    typedef struct
    {
        int to ,next ,cost ,time;
    }STAR;


    typedef struct
    {
        int to ,next ,cost;
    }STAR2;


    typedef struct NODE
    {
        int id ,cost ,time;
        friend bool operator < (NODE a ,NODE b)
        {
            return a.cost > b.cost || a.cost == b.cost && a.time > b.time;
        }
    }NODE;


    int list[N_node] ,tot;
    int list2[N_node] ,tot2;
    int mark[N_node][10000+5];
    int  s_x[N_node][10000+5];
    int s_x2[N_node];
    STAR E[N_edge];
    STAR2 E2[N_edge];
    NODE xin ,tou;


    void add(int a ,int b ,int c ,int d)
    {
        E[++tot].to = b;
        E[tot].cost = c;
        E[tot].time = d;
        E[tot].next = list[a];
        list[a] = tot;
    }


    void add2(int a ,int b ,int c)
    {
        E2[++tot2].to = b;
        E2[tot2].cost = c;
        E2[tot2].next = list2[a];
        list2[a] = tot2;
    }






    void Spfa(int s ,int n ,int maxtime)
    {
        for(int i = 0 ;i <= n ;i ++)
        for(int j = 0 ;j <= maxtime ;j ++)
        s_x[i][j] = INF ,mark[i][j] = 0;
        priority_queue<NODE>q;
        xin.id = 1 ,xin.cost = xin.time = 0;
        q.push(xin);
        s_x[xin.id][xin.time] = 0;
        mark[xin.id][xin.time] = 1;
        while(!q.empty())
        {
            tou = q.top();
            q.pop();
            mark[tou.id][tou.time] = 0;
            for(int k = list[tou.id] ;k ;k = E[k].next)
            {
                xin.id = E[k].to;
                xin.cost = tou.cost + E[k].cost;
                xin.time = tou.time + E[k].time;
                if(xin.time + s_x2[xin.id]> maxtime) continue;
                if(s_x[xin.id][xin.time] > s_x[tou.id][tou.time] + E[k].cost)
                {
                    s_x[xin.id][xin.time] = s_x[tou.id][tou.time] + E[k].cost;
                    if(!mark[xin.id][xin.time])
                    {
                        mark[xin.id][xin.time] = 1;
                        q.push(xin);
                    }
                }


            }
        }
    }


    void Spfa2(int s ,int n)
    {
        int mk[N_node] = {0};
        for(int i = 0 ;i <= n ;i ++)
        s_x2[i] = INF;
        queue<int>q;
        q.push(s);
        mk[s] = 1;
        s_x2[s] = 0;
        while(!q.empty())
        {
            int xin ,tou;
            tou = q.front();
            q.pop();
            mk[tou] = 0;
            for(int k = list2[tou] ;k ;k = E2[k].next)
            {
                xin = E2[k].to;
                if(s_x2[xin] > s_x2[tou] + E2[k].cost)
                {
                    s_x2[xin] = s_x2[tou] + E2[k].cost;
                    if(!mk[xin])
                    {
                        mk[xin] = 1;
                        q.push(xin);
                    }
                }
            }
        }
    }






    int main ()
    {
        int n ,m ,maxtime ,i;
        int a ,b ,c ,d;
        while(~scanf("%d" ,&maxtime))
        {
            scanf("%d %d" ,&n ,&m);
            memset(list ,0 ,sizeof(list));
            memset(list2 ,0 ,sizeof(list2));
            tot = 1 ,tot2 = 1;
            for(i = 1 ;i <= m ;i ++)
            {
                scanf("%d %d %d %d" ,&a ,&b ,&c ,&d);
                add(a ,b ,c ,d);
                add2(b ,a ,d);
            }
            Spfa2(n ,n);
            Spfa(1 ,n ,maxtime);
            int ans = INF;
            for(i = 1 ;i <= maxtime ;i ++)
            if(ans > s_x[n][i]) ans = s_x[n][i];
            if(ans == INF) ans = -1;
            printf("%d " ,ans);
        }
        return 0;
    }









  • 相关阅读:
    关于apache的动态与静态编译
    使用awk处理正则表达式时注意事项
    fedora下apache默认配置
    vim显示行号、语法高亮、自动缩进的设置
    简单介绍apahce内存管理机制
    处理路径上的小技巧
    Educational Codeforces Round 80 (Rated for Div. 2)
    web前端页面性能优化小结
    web标准—可用性、可维护性、可访问性
    雅虎团队经验:网站页面性能优化的 34条黄金守则
  • 原文地址:https://www.cnblogs.com/csnd/p/12062509.html
Copyright © 2011-2022 走看看