0
点赞
收藏
分享

微信扫一扫

POJ1722二维spfa+优先队列优化

青乌 2022-07-27 阅读 59

题意:
     给你一个有向图,然后求从起点到终点的最短,但是还有一个限制,就是总花费不能超过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 条评论