题面
神即将带领一些人去他们的孤寂之境,由于这个世界的不稳定,地点之间的有向道路会不定期地毁坏,出于工作准备,神想知道在某些道路毁坏之后某两点之间的最短路。就是给定一个有向图,现有两个操作,操作 1 是删除一条边(一条边可重复删除),操作 2是询问两个点之间的最短路。
对于 30% 的数据:n,m ≤ 10
对于 50% 的数据:n,m ≤ 50
对于 100% 的数据:n ≤ 200,m ≤ 100000, 操作 1 不超过 200 次,边权不超过 10000
分析
Floyd,又是删边转换成加边。
每次加一条边,只用这一条边去松弛这张图。
因为一条边会被多次删除,所以删边的时候记录一下当前边权,后来加边的时候用这个当前边权松弛。
代码
- #include<bits/stdc++.h>
- using namespace std;
- #define N 220
- #define M 200010
- #define ll long long
- #define INF 123456789
- ll n,m,cnt;
- ll e[N][N],w[M],x[M],y[M],op[M],ans[M];
- template<class T>
- inline void read(T &x)
- {
- x=0;
- static char c=getchar();
- while(c<'0'||c>'9') c=getchar();
- while(c>='0'&&c<='9')
- x=x*10+c-'0',c=getchar();
- }
- int main()
- {
- read(n);read(m);
- for(ll i=1;i<=n;i++)
- for(ll j=1;j<=n;j++)
- read(e[i][j]);
- for(ll i=1;i<=m;i++)
- {
- read(op[i]),read(x[i]),read(y[i]);
- if(op[i]==1)
- {
- w[i]=e[x[i]][y[i]];
- e[x[i]][y[i]]=INF;
- }
- }
- for(ll k=1;k<=n;k++)
- for(ll i=1;i<=n;i++)
- for(ll j=1;j<=n;j++)
- e[i][j]=min(e[i][j],e[i][k]+e[k][j]);
- for(ll z=m;z>=1;z--)
- {
- if(op[z]==1)
- {
- for(ll i=1;i<=n;i++)
- for(ll j=1;j<=n;j++)
- e[i][j]=min(e[i][j],e[i][x[z]]+e[y[z]][j]+w[z]);
- }
- else
- ans[++cnt]=e[x[z]][y[z]];
- }
- for(ll i=cnt;i>=1;i--)
- {
- if(ans[i]>=INF)printf("-1 ");
- else printf("%lld ",ans[i]);
- }
- return 0;
- }