[EC Final 2022] Chase Game 题解
考虑 Pang 教授要怎么追 Shou 教授。一开始如果 Shou 教授一直待在 Pang 教授的攻击范围内那么 Pang 教授就不会动,一旦出了攻击范围 Pang 教授肯定直接就追,具体地,每隔
于是我们可以用 Dijkstra 算法解题。令
注意预处理一下
放代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
main(){
ios::sync_with_stdio(false);
int n,m,k,d,c=1e16; cin>>n>>m>>k>>d;
vector<vector<int> > g(n);
for(int i=1;i<=m;i++){
int u,v; cin>>u>>v;
g[--u].emplace_back(--v);
g[v].emplace_back(u);
}
auto bfs=[&](int u){
queue<int> q; q.emplace(u);
vector<int> d(n);
vector<bool> b(n); b[u]=true;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i:g[u])
if(!b[i])b[i]=true,d[i]=d[u]+1,q.emplace(i);
}
return d;
}; // 预处理最短距离
auto s=[](int l,int r){
return max(0ll,r*(r+1)-l*(l-1)>>1);
}; // 求 l 到 r 的和
auto f=[&](int x){
return x/d*s(1,d)+s(d-x%d+1,d);
}; // 求一路追过去,总共走了 x 个点的伤害
vector<int> dk=bfs(k-1),dn=bfs(n-1),l(n,1e16);
vector<bool> b(n);
priority_queue<pii,vector<pii>,greater<> > q;
q.emplace(l[0]=0,0);
while(!q.empty()){
int u=q.top().second; q.pop();
if(b[u])continue; b[u]=true; // 打标记
for(int i:g[u])
if(dk[i]>=d)c=min(c,l[u]+f(dn[i]+1)); // 注意要 +1,是因为走到 i 这个点也进去
else if(l[u]+d-dk[i]<l[i])q.emplace(l[i]=l[u]+d-dk[i],i); // 更新最短路
} // 使用堆优化 Dijkstra
cout<<min(c,l[n-1])<<endl; // 也有可能都不出范围
return 0;
}