题解:P14912 [NHSPC 2024] 海盗地图
注意到如果对每个点都跑一边最短路的话时间无法接受,但是注意到所有询问的路径长度严格大于 \(\sqrt{n}\)。
也就是说,如果我们随机选一个点在这条路径上的概率有 \(\frac{1}{\sqrt{n}}\)。所以我们选 \(x\) 个点,至少有一个在路径上的概率为 \((1-\frac{1}{\sqrt{n}})^x\),所以我们完全正确的概率大于等于 \(((1-\frac{1}{\sqrt{n}})^x)^q\)。
注意到这里 \(x\) 越大越好,考虑到时间限制,我们取 \(2000\) 左右即可(其实可以取到 \(1500\) 的,但是更保险)
code
#include<bits/stdc++.h>
using namespace std;
mt19937 myrand(time(nullptr));
int tot , head[10005] , q;
struct edge{
int to , nxt;
}ed[200005];
void add_edge(int u , int v){
tot++ , ed[tot].to = v , ed[tot].nxt = head[u] , head[u] = tot;
}
int n , m , dis[2005][10005] , id[2005];
queue<int> Q;
void bfs(int id , int s){
Q.push(s);
for(int i=1;i<=n;i++)dis[id][i] = 0x3f3f3f3f;
dis[id][s] = 0;
while(!Q.empty()){
int u = Q.front();Q.pop();
for(int j=head[u];j;j=ed[j].nxt){
int v = ed[j].to;
if(dis[id][v]>=0x3f3f3f3f)dis[id][v] = dis[id][u] + 1 , Q.push(v);
}
}
}
int main(){
cin >> n >> m >> q;
for(int i=1;i<=m;i++){
int u , v;cin >> u >> v;
add_edge(u,v) , add_edge(v,u);
}
for(int i=0;i<2000&&i<n;i++){
id[i] = myrand() % n + 1;
bfs(i,id[i]);
}
for(int i=1;i<=q;i++){
int minn = 0x3f3f3f3f , s , t;cin >> s >> t;
for(int j=0;j<2000&&j<n;j++)minn = min(minn,dis[j][s]+dis[j][t]);
cout << minn << " ";
}
return 0;
}

浙公网安备 33010602011771号