题意
给一个n个点m条边的无向图和起点s,现在可以任意删掉一个除s以外的点,问最多有多少个点的最短路发生变化。
n<=200000,m<=300000
分析
其实这题就是问你把这个无向图构造一个最短路的DAG,求这个每个点能影响多少个点,其实也就是让你做支配树。
代码
#include <bits/stdc++.h>
#define pb(x) push_back(x)
const int N = 200005;
const long long INF = (long long)1e15;
typedef long long ll;
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
return x * f;
}
int n,m,s;
struct Edge
{
int to,next,c;
bool op;
}e[N * 3];
int next[N];
int cnt;
void add(int x,int y,int z)
{
e[++cnt].to = y, e[cnt].c = z, e[cnt].next = next[x], next[x] = cnt;
e[++cnt].to = x, e[cnt].c = z, e[cnt].next = next[y], next[y] = cnt;
}
ll dis[N];
bool vis[N];
void spfa()
{
for (int i = 1; i <= n; i++)
dis[i] = INF;
dis[s] = 0;
vis[s] = 1;
std::queue<int> Q;
Q.push(s);
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i = next[x]; i; i = e[i].next)
{
int v = e[i].to;
if (dis[v] > dis[x] + e[i].c)
{
dis[v] = dis[x] + e[i].c;
if (!vis[v])
{
Q.push(v);
vis[v] = 1;
}
}
}
vis[x] = 0;
}
}
int d[N];
std::vector<int> V[N];
void rebuild()
{
memset(vis, 0, sizeof(vis));
std::queue<int> Q;
Q.push(s);
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i = next[x]; i; i = e[i].next)
{
int v = e[i].to;
if (dis[v] == dis[x] + e[i].c)
{
d[v]++;
e[i].op = 1;
V[v].pb(x);
if (!vis[v])
{
Q.push(v);
vis[v] = 1;
}
}
}
}
}
int a[N];
int tot;
void topSort()
{
a[++tot] = s;
for (int j = 1; j <= tot; j++)
{
int x = a[j];
for (int i = next[x]; i; i = e[i].next)
{
if (e[i].op == 1)
{
d[e[i].to]--;
if (!d[e[i].to])
a[++tot] = e[i].to;
}
}
}
}
int fa[N][20];
int dep[N];
int lca(int x,int y)
{
if (dep[x] < dep[y])
std::swap(x,y);
for (int i = 18; i >= 0; i--)
if (dep[fa[x][i]] >= dep[y])
x = fa[x][i];
if (x == y)
return x;
for (int i = 18; i >= 0; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
}
int size[N];
void solve()
{
for (int i = 1; i <= tot; i++)
{
int x = a[i];
for (int j = 0; j < V[x].size(); j++)
if (!fa[x][0])
fa[x][0] = V[x][j];
else fa[x][0] = lca(fa[x][0], V[x][j]);
dep[x] = dep[fa[x][0]] + 1;
for (int j = 1; j <= 18; j++)
fa[x][j] = fa[fa[x][j - 1]][j - 1];
}
for (int i = tot; i >= 1; i--)
size[a[i]]++, size[fa[a[i]][0]] += size[a[i]];
int ans = 0;
for (int i = 2; i <= tot; i++)
ans = std::max(ans, size[a[i]]);
printf("%d\n",ans);
}
int main()
{
n = read(), m = read(), s = read();
for (int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
add(x,y,z);
}
spfa();
rebuild();
topSort();
solve();
}