标签:一个 void trick floyd 有向图 text ons bit mat
给一个有向图,有两个操作,一个是删除一条边,一个是询问两点之间最短路,\(n \le 200,q \le 100000\),其中操作一(删边)不超过\(200\)次。
一个反向操作的 \(\texttt{trick}\),相当于先把所有要删的边删除,形成一个新图\(\mathbf{G}‘\),对\(\mathbf{G}‘\)先\(\operatorname{Floyd}\),后反向进行加边(\(\texttt{add Edge}\))操作,每次加边更新\(f_{i,j}\),\(f_{i,j} = \min(f_{i,j},f_{i,u} + f_{v,j} + f_{u,v})\),其中\((u,v,w)\)为新加边。
时间复杂度\(\mathcal{O}(n^3 + 200n^2)\)
#include <bits/stdc++.h>
using namespace std;
const int N = 205;
const long long inf = 5e11;
int n, m;
struct node
{
int opt, x, y;
};
long long f[N][N], f2[N][N];
int vis[N][N];
long long ans[100005];
int top = 0;
node q[100005];
void FIO(void)
{
freopen("journey.in", "r", stdin);
freopen("journey.out", "w", stdout);
return;
}
void update(int u, int v)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
f[i][j] = min(f[i][j], f[i][u] + f[v][j] + f[u][v]);
}
}
return;
}
int main(void)
{
FIO();
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
f[i][j] = f2[i][j] = (i == j) ? 0 : inf;
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
scanf("%lld", &f[i][j]);
f2[i][j] = f[i][j];
}
}
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &q[i].opt, &q[i].x, &q[i].y);
if (q[i].opt == 1)
{
if (vis[q[i].x][q[i].y] == 0)
vis[q[i].x][q[i].y] = i;
f[q[i].x][q[i].y] = inf;
}
}
for (int k = 1; k <= n; k++)
{
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}
}
}
for (int i = m; i >= 1; i--)
{
int u = q[i].x, v = q[i].y;
if (q[i].opt == 1)
{
if (vis[u][v] != i)
continue;
f[u][v] = min(f[u][v], f2[u][v]);
update(u, v);
}
else
{
ans[++top] = f[u][v];
}
}
for (int i = top; i >= 1; i--)
printf("%lld\n", (ans[i] >= inf) ? -1 : ans[i]);
return 0;
}
标签:一个 void trick floyd 有向图 text ons bit mat
原文地址:https://www.cnblogs.com/luyiming123blog/p/lv_cheng.html