题目大意:
给你
n(n<=2∗105)
n
(
n
<=
2
∗
10
5
)
个点
m(m<=3∗105)
m
(
m
<=
3
∗
10
5
)
条边的无向图,每条边有长度
w(1<=w<=109)
w
(
1
<=
w
<=
10
9
)
,问删除某个点(不包括
s
s
)最多能影响多少条从出发到其他
n−1
n
−
1
个点的最短路。
分析:
先把最短路求出来,然后连成最短路树(其实是一个
DAG
D
A
G
),
s
s
到任何点的最短路都在树上。
然后在这个上建支配树,断掉某个点的答案就是它所在
dfs
d
f
s
树的子树上有多少个点能被它支配,直接用支配链转移即可。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#define LL long long
const int maxn=2e5+7;
const int maxe=3e5+7;
const LL inf=1e16+7;
using namespace std;
int n,m,s,x,y,cnt;
int ls[maxn],last[maxn],idom[maxn],sdom[maxn],fa[maxn];
int p[maxn],val[maxn],f[maxn],dfn[maxn],id[maxn];
vector <int> dom[maxn],pre[maxn];
int v[maxn];
LL dis[maxn],w;
struct edge{
int x,y,next;
LL w;
}e[maxe*2];
struct node{
int y,next;
}g[maxe*2];
struct rec{
int x;
LL d;
};
priority_queue <rec> q;
bool operator <(rec x,rec y)
{
return x.d>y.d;
}
void dij()
{
for (int i=1;i<=n;i++) dis[i]=inf;
dis[s]=0;
q.push((rec){s,0});
while (!q.empty())
{
rec u=q.top();
q.pop();
int x=u.x;
if (v[x]) continue;
v[x]=1;
for (int j=last[x];j>0;j=e[j].next)
{
int y=e[j].y;
if (dis[y]>dis[x]+e[j].w)
{
dis[y]=dis[x]+e[j].w;
q.push((rec){y,dis[y]});
}
}
}
}
void add(int x,int y)
{
g[++cnt]=(node){y,ls[x]};
ls[x]=cnt;
}
void dfs(int x)
{
dfn[x]=++cnt;
id[cnt]=x;
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
pre[y].push_back(x);
if (!dfn[y])
{
fa[y]=x;
dfs(y);
}
}
}
int smin(int x,int y)
{
if (dfn[x]<dfn[y]) return x;
return y;
}
int get(int x)
{
if (p[x]==x) return x;
int y=get(p[x]);
if (dfn[sdom[val[p[x]]]]<dfn[sdom[val[x]]]) val[x]=val[p[x]];
p[x]=y;
return y;
}
void DMT()
{
for (int i=cnt;i>0;i--)
{
int x=id[i];
if (!pre[x].empty())
{
for (int j=0;j<pre[x].size();j++)
{
int y=pre[x][j];
if (dfn[y]<dfn[x]) sdom[x]=smin(sdom[x],y);
else
{
get(y);
sdom[x]=smin(sdom[x],sdom[val[y]]);
}
}
}
pre[x].clear();
p[x]=fa[x];
dom[sdom[x]].push_back(x);
if (!dom[fa[x]].empty())
{
for (int j=0;j<dom[fa[x]].size();j++)
{
int y=dom[fa[x]][j];
get(y);
int d=val[y];
if (dfn[sdom[d]]>=dfn[sdom[y]]) idom[y]=sdom[y];
else idom[y]=d;
}
dom[fa[x]].clear();
}
}
for (int i=1;i<=cnt;i++)
{
int x=id[i];
if (idom[x]!=sdom[x]) idom[x]=idom[idom[x]];
}
for (int i=cnt;i>0;i--)
{
x=id[i];
f[idom[x]]+=f[x];
}
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for (int i=1;i<=m;i++)
{
scanf("%d%d%lld",&x,&y,&w);
e[i].x=x;
e[i].y=y;
e[i].w=w;
e[i].next=last[x];
last[x]=i;
e[i+m].x=y;
e[i+m].y=x;
e[i+m].w=w;
e[i+m].next=last[y];
last[y]=i+m;
}
dij();
for (int i=1;i<=m*2;i++)
{
int x=e[i].x,y=e[i].y;
if (dis[x]+e[i].w==dis[y]) add(x,y);
}
cnt=0;
dfs(s);
for (int i=1;i<=n;i++)
{
p[i]=val[i]=sdom[i]=i;
f[i]=1;
}
DMT();
int ans=0;
for (int i=2;i<=cnt;i++)
{
int x=id[i];
ans=max(ans,f[x]);
}
printf("%d",ans);
}