[ABC416E] Development
题目-[ABC416E] Development
算法关键词:图论,最短路
题目大意:一张图有 \(n\) 个节点和 \(m\) 条无向边,边权为 \(m_i\),其中有 \(k\) 个特殊节点,每个特殊节点间有一条边权为 \(T\) 的无向边。问\(\sum_{x=1}^{N}\sum_{y=1}^{N}f(x,y)\)。(\(f(x,y)\)代表从 \(x\) 城市到 \(y\) 城市的最短路)。
很显然这道题和最短路密切相关 (没有什么乱搞成分),又因为需要求全源最短路,看眼数据范围只到 \(0 \le n \le 500\),可以放心选择floyd。但显然不能每次操作都重新建图(时间复杂度来到 \(O(Qn^3)\))。那么我们该怎么办呢OvO?
既然每次添加的长度都相同,那么我们不妨假设每一次建设飞机场都相当于连接到一个“中心节点”(当然这个点是不存在的),这样每次建设飞机场都转换成了新建一条边,就很好实现了,时间复杂度在\(O(Qn^2)\),可以接受。
代码实现,额码力还是太差了。
#include<bits/stdc++.h>
using namespace std;
int floyd[505][505];
int main(){
int n,m,Q,T;
cin>>n>>m;
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n+1;j++)
if(i!=j)floyd[i][j]=1e18;
while(m--){
int u,v,w;
cin>>u>>v>>w;
w*=2;
floyd[u][v]=min(floyd[u][v],w);
floyd[v][u]=min(floyd[v][u],w);
}
cin>>m>>T;
while(m--){
int u=n+1,v,w=T;
cin>>v;
floyd[u][v]=min(floyd[u][v],w);
floyd[v][u]=min(floyd[v][u],w);
}
for(int k=1;k<=n+1;k++)
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n+1;j++)
floyd[i][j]=min({floyd[i][j],floyd[i][k]+floyd[k][j]});
cin>>Q;
while(Q--){
int op;
cin>>op;
if(op==1){
int u,v,w;
cin>>u>>v>>w;
w*=2;
for(int j=1;j<=n+1;j++)
for(int k=j+1;k<=n+1;k++)
floyd[k][j]=floyd[j][k]=min({floyd[j][k],
floyd[j][u]+floyd[v][k]+w,floyd[j][v]+floyd[u][k]+w});
}else if(op==2){
int u=n+1,v,w=T;
cin>>v;
for(int j=1;j<=n+1;j++)
for(int k=j+1;k<=n+1;k++)
floyd[k][j]=floyd[j][k]=min({floyd[j][k],
floyd[j][u]+floyd[v][k]+w,floyd[j][v]+floyd[u][k]+w});
}else{
int ans=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(floyd[i][j]!=1e18)
ans+=floyd[i][j];
cout<<ans/2<<endl;
}
}
return 0;
}