『题解』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;
}