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\n" ,ans);
    }
    return 0;
}









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值