Link
题意:
有n个城市,每个城市有个辣度,给你个图,有q次询问求某个点开始,忍耐度为w,求最近辣度<=w的最短路,边权为1。
q
<
=
5
e
5
n
<
=
1
e
5
m
<
=
1
e
5
w
i
,
w
<
=
100
q<=5e5 \space n<=1e5 \space\space \space m<=1e5 \space wi,w<=100
q<=5e5 n<=1e5 m<=1e5 wi,w<=100
思路:
由于边权为1,考虑最短路,并且由于辣度还小为100
d
i
s
t
[
u
]
[
v
]
dist[u][v]
dist[u][v]代表到u辣度为v的最短路径,那么就可以多源bfs,每次枚举辣度值i,把辣度刚好等于i的放进队列里让他们去更新别的点,然后由于有些点的最优值不一定是w,我们可以类似递推去处理<=w的前缀最小值。
复杂度:
O
(
100
(
n
+
m
)
+
q
)
O(100(n+m)+q)
O(100(n+m)+q)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;
const int N=100010;
int dist[N][110];
vector<int>v[N];
int n,m,q;
int w[N];
void solve(int x){
queue<int>q;
for(int i=1;i<=n;i++)
if(w[i]==x)
q.push(i),dist[i][x]=0;
while(q.size()){
auto tt=q.front();
q.pop();
for(auto j:v[tt])
{
if(dist[j][x]!=0x3f3f3f3f) continue;
dist[j][x]=dist[tt][x]+1;
q.push(j);
}
}
}
int main()
{
memset(dist,0x3f,sizeof dist);
cin>>n>>m>>q;
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
v[a].emplace_back(b);
v[b].emplace_back(a);
}
for(int i=1;i<=100;i++) solve(i);
for(int i=2;i<=100;i++)
for(int j=1;j<=n;j++)
dist[j][i]=min(dist[j][i-1],dist[j][i]);
while(q--){
int x,d;
scanf("%d%d",&x,&d);
if(dist[x][d]==0x3f3f3f3f) puts("-1");
else printf("%d\n",dist[x][d]);
}
}
/**
* In every life we have some trouble
* When you worry you make it double
* Don't worry,be happy.
**/