tkm2013
2024-11-18 20:42:03
在这道题中,比普通的最短路题还要多了一个地铁,所以我们重点来考虑这个地铁。
如题,地铁只有一趟,所以我们可以选择坐或者不坐,也可以是中途下车,而不会中途上车。如果你比地铁先一步到达地铁站,还是要等待地铁,所以和一开始就上地铁的时间是一样的,所以坐地铁就只会有三种情况。
然后我们还需要求出每个点到终点的距离,不要每一次都重新求,那样时间复杂度会有点高,边权都为1,我们可以使用广搜求最短路,由于我们不好以每个点为起点,然后往
#include<bits/stdc++.h>
using namespace std;
int n,m,q;
int dis[200005];
vector<int>g[200005];
int s[200005];
void bfs(){//跑遍最短路
for(int i=1;i<n;i++){//初始化
dis[i]=2e9;
}
queue<int>q;
q.push(n);
while(q.size()){
int u=q.front();
q.pop();
for(auto v:g[u]){
if(dis[v]==2e9){
q.push(v);
dis[v]=dis[u]+1;
}
}
}
return;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>q;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
g[v].push_back(u);
}
for(int i=1;i<=n;i++){
cin>>s[i];
}
bfs();
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
swap(s[x],s[y]);
int minn=2e9;
for(int j=1;j<=n;j++){//枚举下车时刻
minn=min(minn,dis[s[j]]+j-1);
}
cout<<minn<<"\n";
}
return 0;
}
然后我们就需要对这份代码进行优化了,枚举的时间复杂度是
最优,看到这两个字,就让人想到了优先队列,我们可以先把没有任何交换过的答案放进优先队列,每次交换后把在
#include<bits/stdc++.h>
#include<vector>
using namespace std;
int n,m,f;
int dis[200005];
vector<int>g[200005];
int s[200005];
void bfs(){
for(int i=1;i<n;i++){
dis[i]=2e9;
}
queue<int>q;
q.push(n);
while(q.size()){
int u=q.front();
q.pop();
for(auto v:g[u]){
if(dis[v]==2e9){
q.push(v);
dis[v]=dis[u]+1;
}
}
}
return;
}
struct no{
int pos,id;
bool operator<(const no&x)const
{
return pos-1+dis[id]>x.pos-1+dis[x.id];
}
};
priority_queue<no>q;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>f;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
g[v].push_back(u);
}
for(int i=1;i<=n;i++){
cin>>s[i];
}
bfs();
for(int i=1;i<=n;i++){
q.push({i,s[i]});
}
for(int i=1;i<=f;i++){
int x,y;
cin>>x>>y;
swap(s[x],s[y]);
q.push({x,s[x]});
q.push({y,s[y]});
while(s[q.top().pos]!=q.top().id){//将对不上号的给踢出去
q.pop();
}
cout<<q.top().pos-1+dis[q.top().id]<<"\n";
}
return 0;
}
十年洛谷一场空,复制题解名变棕。