『题解』SPOJ SP30669 ADATRIP - Ada and Trip

题目传送门

题目大意

给定一张无向图,并给出 \(q\) 个询问。对于每个询问,给出起始点 \(s_i\),请求出距离起始点最短路最远的点,并求出最远的点的个数。

\(1 \le n \le 5 \times 10^5,1 \le m \le 10^6,\max\{n,m\} \times q \le 10^7\)

保证边权不为负。

时间限制 \(5.5s\),空间限制 \(1.46\)GB。

思路

第一眼题面:[数据删除]范围这么大...怎么跑最短路啊......

第二眼题面:哦时限 \(5.5s\) 那没事了......

此题翻译数据范围假了,至少在我写题解的时候,\(n\)\(5 \times 10^5\)

既然时限这么大,那么就可以考虑下全源最短路。

但是 \(n \le 5 \times 10^5\),爆栈了要。

既然栈会寄,那就只好时间换空间每次询问都跑一遍最短路了。

这题可以 dijkstra 或 SPFA,但考虑到 SPFA 寄了,我就写 dijkstra 了。

每次跑完后都循环一遍找最远的一个点,若这个点比先前找到的最远的点还要远,那么最远的点数统计变量也要清空,原因显然。

注意开 long long。

代码

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
template<typename T=long long>
inline T read(){
    T X=0; bool flag=1; char ch=getchar();
    while(ch<'0' || ch>'9'){if(ch=='-') flag=0; ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<1)+(X<<3)+ch-'0',ch=getchar();
    if(flag) return X;
    return ~(X-1);
}

typedef long long ll;
const ll N=5e5+5,M=2e6+5,inf=0x3f3f3f3f3f3f3f3f;
struct edge{
    int to,nxt;
    ll val;
}e[M];
int n,m,q,u,v,s;
ll w,ans,cnt;
int head[N],top;
ll dist[N];
int vis[N];
priority_queue<pair<int,int>> h;

void add(int u,int v,int w){
    top++;
    e[top].to=v;
    e[top].val=w;
    e[top].nxt=head[u];
    head[u]=top;
}

void dijkstra(int s){
    for(int i=0; i<n; i++)
        dist[i]=inf,vis[i]=0;
    h.push(make_pair(0,s));
    dist[s]=0;
    while(!h.empty()){
        u=h.top().second;
        h.pop();
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=head[u]; i; i=e[i].nxt){
            v=e[i].to;
            if(dist[v]>dist[u]+e[i].val){
                dist[v]=dist[u]+e[i].val;
                h.push(make_pair(-dist[v],v));
            }
        }
    }
}

signed main(){
    n=read(),m=read(),q=read();
    while(m--){
        u=read(),v=read(),w=read();
        add(u,v,w);
        add(v,u,w);
    }
    while(q--){
        s=read();
        dijkstra(s);
        ans=-114514,cnt=1;
        for(int i=0; i<n; i++)
            if(dist[i]==inf) continue;
            else if(ans<dist[i]){
                ans=dist[i];
                cnt=1;
            }else if(ans==dist[i]) cnt++;
        printf("%lld %lld\n",ans,cnt);
    }
    return 0;
}
posted @ 2022-07-19 16:18  仙山有茗  阅读(32)  评论(0编辑  收藏  举报