关于二分+dij堆优化超时的疑惑

P1462 通往奥格瑞玛的道路

leo12334 @ 2023-01-12 14:04:51

用二分和dij堆优化写的,一开始没有加

if(vis[y])continue;

然后就只有60分,有4个点TLE,加了以后就AC了。但我在前边取出队列元素x的时候会进行vis[x]判断,如果访问过就会跳过,后边再加上vis[y]的判断仅会省略两组if和一组入队出队操作,这对时间效率影响很大吗?

#include<bits/stdc++.h>
using namespace std;
#define N 123456
#define M 223456
#define pii pair<int,int>
#define mp(x,y) make_pair(x,y)
int n,m,b,x,y,z,l=1e9+1,r,mid;
int a[N],vis[N],dis[N],ans,cnt,head[N],cost[N],maxn;
struct edge{
    int to,next,w;
}e[M];
void add(int x,int y,int z){
    e[++cnt].to=y;
    e[cnt].next=head[x];
    e[cnt].w=z;
    head[x]=cnt;
}
int dijiesitela(int max_cost){
    priority_queue< pii >q;
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    dis[1]=0;
    q.push(mp(0,1));
    while(q.size()){
        int x=q.top().second;q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].to,v=e[i].w;
            if(vis[y])continue;
            if(cost[y]>max_cost) continue;//费用大于ans的城市要跳过
            if(dis[y]>dis[x]+v) dis[y]=dis[x]+v;
            q.push(mp(-dis[y],y));
        }
    }

    return dis[n];
}
int main(){
    cin>>n>>m>>b;
    for(int i=1;i<=n;i++){
        cin>>cost[i];
        r=max(r,cost[i]);
    }
    l=max(cost[1],cost[n]);
    while(m--){
        cin>>x>>y>>z;
        add(x,y,z);
        add(y,x,z);
    }
    if(dijiesitela(r)>b){puts("AFK");return 0;}//先测试最短路的可行性

    while(l<r){
        mid=(l+r)/2;
        if(dijiesitela(mid)>b)l=mid+1;
        else r=mid;
    }
    cout<<l<<endl;
}

by 晴空一鹤 @ 2023-01-12 14:15:42

@leo12334 考虑是个稠密图就很劣了(进队的点扩大几倍),再加上这题本就有点卡常


by olegekei @ 2023-01-12 14:20:49

@leo12334 你可以试着开一个 O2,对速度有极大的提升


by leo12334 @ 2023-01-12 15:08:50

谢谢两位大佬解答!


|