8.5 mx放学路
__S08577__ · · 题解
思路
Dij+二分。
一眼二分答案,二分最小能量值。
Dij是板子。注意两点之间的距离是最多能放传送锚点的个数,这里分讨,如果两点之间的距离不能和能量值整除,那么锚点个数为
代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<set>
using namespace std;
#define int long long
#define ll long long
#define Endl cout<<endl;
#define xy cout<<"xy";
#define yx cout<<"yx";
#define pii pair<int,int>
#define lowbit(x) x&(-x)
const int N=5e5+10;//注意修改
const int mod=1e9+9;
const int Max=2e9+10;
struct node{
int v,d;
bool operator < (const node&b) const{
return d>b.d;
}
};
pii a[N];
int vis[N],ddis[N];
int n,m,x;
int dis(int u,int v,int k){
int dis_d=abs(a[u].first-a[v].first)+abs(a[u].second-a[v].second);
if(dis_d%k){
return dis_d/k;
}
else{
return max(0ll,dis_d/k-1);
}
}
int Dij(int X){
priority_queue<node> q;
ddis[m+1]=0;
q.push(node{m+1,0});
while(!q.empty()){
node t=q.top();
q.pop();
if(vis[t.v]) continue;
vis[t.v]=1;
for(int i=1;i<=m+2;i++){
if(vis[i]) continue;
int w=dis(t.v,i,X);
if(ddis[i]>ddis[t.v]+w){
ddis[i]=ddis[t.v]+w;
if(!vis[i]){
q.push(node{i,ddis[i]});
}
}
}
}
return ddis[m+2];
}
bool check(int X){
for(int i=1;i<=m+2;i++) vis[i]=0;
for(int i=1;i<=m+2;i++) ddis[i]=Max;
return Dij(X)<=x;
}
signed main(){
// freopen("road.in","r",stdin);
// freopen("road.out","w",stdout);
int sx,sy,ex,ey;
cin>>n>>m>>x;
cin>>sx>>sy>>ex>>ey;
for(int i=1;i<=m;i++){
cin>>a[i].first>>a[i].second;
}
a[m+1]={sx,sy};
a[m+2]={ex,ey};
int l=1,r=2e9,res=0;
while(l<r){
int mid=(l+r)>>1;
if(check(mid)){
r=mid;
}
else l=mid+1;
}
cout<<l;
return 0;
}
//唐儿祭天,法力无边。
/*
*/