[ABC416]E-Development解题报告
前言
赛时这题交了三发,都被卡了,最终止步于rk3248 QwQ
问题简述
动态维护一张无向图,支持修改,计算所有点对的最短路径总和。原题链接
切入
看到 \(N \leq 500\) 很容易想到使用 \(Floyd_Warshall\) 来对整张图进行一个 \(O(N^3)\) 的遍历来统计各个点之间的最短路
对于机场而言,我们可以用一个桶来维护,在遍历每个点的时候单独判断是否有机场,然后对边权与t进行比较
显然对于每次 \(opt=3\) 的询问我们都要做一次 \(Floyd\) ,总时间复杂度就是 \(O(pN^3)\) \(p\)代表\(q\)中 \(opt=3\) 的次数
这样的时间复杂度在 \(p\) 很大时是无法接受的,最多只能过掉7个点
优化
我们发现, \(O(N^3)\) 询问的效率太低了,对于每次建边,可以把u和v单独拿出来进行 \(Floyd\)
对于机场而言,可以建一个键值为 \(N+1\) 的天空中转点,从机场到天空的边权为 \(t\) ,从天空到机场的边权为 \(0\) ,将天空和机场的点拿出来进行 \(Floyd\)
这样,我们便有了一个均匀的为 \(O(N^3+qN^2)\) 的复杂度,足够过掉此题
AC Code
点击查看代码
// Problem: E - Development
// Contest: AtCoder - AtCoder Beginner Contest 416
// URL: https://atcoder.jp/contests/abc416/tasks/abc416_e
// Memory Limit: 1024 MB
// Time Limit: 3500 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
#define endll " "
#define it inline int
#define iv inline void
#define fre(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
#pragma GCC optimize(0)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
const int MAXN=510;
const int INF=1e18;
const int mod=998244353;
it gcd(int x,int y){return y==0?x:gcd(y,x%y);}
it lcm(int x,int y){return x/gcd(x,y)*y;}
it max(int x,int y){return x>y?x:y;}
it min(int x,int y){return x<y?x:y;}
it qpow(int x,int m,int mod)
{
int res=1,bas=x%mod;
while(m)
{
if(m&1) res=(res*bas)%mod;
bas=(bas*bas)%mod,m>>=1;
}
return res%mod;
}
int n,m,u,v,w,k,t,q,opt,x,y,dis[MAXN][MAXN];
bool f[MAXN];
it query()
{
int res=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(dis[i][j]!=INF)
res+=dis[i][j];
}
}
return res;
}
iv update(int k)
{
for(int i=1;i<=n+1;i++)
{
if(dis[i][k]==INF)
continue;
for(int j=1;j<=n+1;j++)
{
if(dis[k][j]!=INF && dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n+1;i++)
for(int j=1;j<=n+1;j++)
dis[i][j]=(i==j)?0:INF;
for(int i=1;i<=m;i++)
{
cin>>u>>v>>w;
if(w<dis[u][v])
{
dis[u][v]=w;
dis[v][u]=w;
}
}
cin>>k>>t;
for(int i=1;i<=k;i++)
{
cin>>x;
f[x]=1;
dis[x][n+1]=t;
dis[n+1][x]=0;
}
for(int k=1;k<=n+1;k++)
{
for(int i=1;i<=n+1;i++)
{
if(dis[i][k]==INF)
continue;
for(int j=1;j<=n+1;j++)
{
if(dis[k][j]!=INF && dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
cin>>q;
while(q--)
{
cin>>opt;
if(opt==1)
{
cin>>u>>v>>w;
if(w>=dis[u][v])
continue; //只有当新路更短时才更新
dis[u][v]=w;
dis[v][u]=w;
update(u);
update(v);
}
if(opt==2)
{
cin>>x;
if(f[x]==1)
continue;
f[x]=1;
dis[x][n+1]=t;
dis[n+1][x]=0;
update(x);
update(n+1);
}
if(opt==3)
{
cout<<query()<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号