Codeforces 757F. Team Rocket Rises Again
Description
给出 \(n\) 个点 \(m\) 条边的无向图 , 和一个起点 \(S\) ,问让你删除一个点和与这个点相连的边,你可以选择删除一个点, 最大化到 \(S\) 的最短路发生改变的点数
题面
Solution
按照最短路为拓扑序建立灭绝树
灭绝树的定义是:如果一个点灭绝,那么它的子树内的点都会灭绝
\(dis[u]+l=dis[x]\) ,那么删除这个点就会导致最短路发生变化,如果有多个点都满足,删除所有的才会发生变化
那么怎么才能删除一个点使得它变化?删除所有满足 \(dis[u]+l=dis[x]\) 的 \(u\) 的 \(lca\),或者 \(lca\) 以上的点即可
我们就在灭绝树上连边 \((lca,x)\) , 最后统计一遍 \(max(size[i])\) 就是答案
#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
}
typedef long long ll;
const int N=2e5+10;
int n,m,S,dis[N*4],head[N],nxt[N*4],to[N*4],num=0,q[N],top=0;
inline void link(int x,int y,int z){
nxt[++num]=head[x];to[num]=y;head[x]=num;dis[num]=z;
nxt[++num]=head[y];to[num]=x;head[y]=num;dis[num]=z;
}
ll f[N];int fa[N][20],dep[N],sz[N];
struct data{int x;ll y;};
inline bool operator <(data i,data j){return i.y>j.y;}
priority_queue<data>Q;
inline void dj(){
memset(f,127/3,sizeof(f));
Q.push((data){S,0});f[S]=0;
while(!Q.empty()){
while(f[Q.top().x]!=Q.top().y)Q.pop();
int x=Q.top().x;Q.pop();q[++top]=x;
if(top==n)break;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(f[x]+dis[i]<f[u])f[u]=f[x]+dis[i],Q.push((data){u,f[u]});
}
}
}
inline int lca(int x,int y){
if(dep[x]<dep[y])swap(x,y);
for(int i=18;i>=0;i--)if((dep[x]-dep[y])>>i&1)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 main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
int x,y,z;
cin>>n>>m>>S;
for(int i=1;i<=m;i++){
gi(x);gi(y);gi(z);
link(x,y,z);
}
dj();
for(int i=1;i<=top;i++){
x=q[i];z=-1;
for(int j=head[x];j;j=nxt[j]){
y=to[j];
if(f[y]+dis[j]==f[x]){
if(z==-1)z=y;
else z=lca(y,z);
}
}
if(z==-1)continue;
dep[x]=dep[z]+1,fa[x][0]=z;
for(int j=1;j<=18;j++)fa[x][j]=fa[fa[x][j-1]][j-1];
}
for(int i=1;i<=n;i++)sz[i]=1;
int ans=0;
for(int i=top;i>=1;i--){
x=q[i];
sz[fa[x][0]]+=sz[x];
if(x!=S)ans=max(ans,sz[x]);
}
cout<<ans<<endl;
return 0;
}