题解:AT_abc416_e [ABC416E] Development
题意
A 国有
接下来有
- 添加一条道路。
- 新增一个机场。
- 询问所有城市对之间的最短路径总和。
题解
注意到
一开始输入完整张图后,可以先跑一遍 Floyd,对于机场,先不考虑两两连边,而是把所有机场先存到一个数组里。
接下来处理操作:
-
让我们先考虑普通的 Floyd 的实现,分别枚举
k,i,j ,以k 为中间节点转移。现在可以把给出的边
(u,v,w) 当作那个k ,原本是i \to k \to j 转移,现在变为i \to u \to v \to j 或者是i \to v \to u \to j 。 -
把新增的机场存起来。
-
枚举
i,j ,则i \to j 的最短距离有两种情况:- 不使用机场,则就是刚才用 Floyd 求出的答案。
- 使用机场,先记录每个点与它最近的机场
d_i ,最后的答案就是i \to d_i+t+d_j \to j 。
时间复杂度
代码
#include<bits/stdc++.h>
#define int long long
#define double long double
#define bug cout<<"___songge888___"<<'\n';
using namespace std;
int n,m;
int k,t,q;
vector<int> d;
int dis[555][555];
int di[555];
void add(int u,int v,int o){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dis[i][u]+o+dis[v][j]<dis[i][j]){
dis[i][j]=dis[i][u]+o+dis[v][j];
}
}
}
}
signed main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n>>m;
memset(di,0x3f,sizeof di);
memset(dis,0x3f,sizeof dis);
for(int i=1;i<=n;i++){
dis[i][i]=0;
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
dis[u][v]=dis[v][u]=min(dis[u][v],w);
}
cin>>k>>t;
for(int i=1;i<=k;i++){
int x;
cin>>x;
d.push_back(x);
}
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(dis[i][k]+dis[k][j]<dis[i][j]){
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
}
cin>>q;
while(q--){
int op;
cin>>op;
if(op==1){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
else if(op==2){
int x;
cin>>x;
d.push_back(x);
}
else{
int ans=0;
for(int i=1;i<=n;i++){
for(auto j:d){
di[i]=min(di[i],dis[i][j]);
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
int pos=dis[i][j];
if(d.size()){
dis[i][j]=min(dis[i][j],di[i]+t+di[j]);
}
if(dis[i][j]<0x3f3f3f3f3f3f3f3f){
ans+=dis[i][j];
}
}
}
cout<<ans<<'\n';
}
}
return 0;
}
提交记录