【CF757F】 Team Rocket Rises Again 【支配树】
Description
- 传送门
- 题意:给定一个\(n\)个点,\(m\)条边的带权无向图,和起点\(s\)。选择一个点\(u\)(\(u \neq s\)),使在图中删掉点\(u\)后,有尽可能多的点到\(s\)的最短距离改变。
- \(1\le n \le 2*10^5,1\le m \le 3*10^5\),给出的图无重边无自环,不保证连通。
Solution
破坏最短路可以建出最短路树后转化为破坏所有路径,于是就变成了一个裸的支配树问题,我们只需要求出除\(s\)之外所有点支配树上的子树大小的最大值即可。
最短路树是一个\(DAG\),于是套支配树的模板即可。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=6e5+10;
typedef long long ll;
typedef pair<ll,int> pli;
#define mp make_pair
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
int n,m,s;
struct node{
int v,w,nxt;
};
struct graph{
int first[N],cnt;
node e[N];
inline void add(int u,int v,int w=0){
e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=first[u];first[u]=cnt;
}
}g,tr;//原图与最短路树
int vis[N];
ll dis[N];
vector<int> ru[N];
inline void dijkstra(){
priority_queue<pli> q;
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
q.push(mp(0,s));
while(!q.empty()){
int u=q.top().second;q.pop();if(vis[u]) continue;
for(int i=g.first[u];i;i=g.e[i].nxt){
int v=g.e[i].v,w=g.e[i].w;
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
q.push(make_pair(-dis[v],v));
}
}
}
for(int i=1;i<=n;++i){
for(int j=g.first[i];j;j=g.e[j].nxt){
int v=g.e[j].v;
if(dis[v]!=dis[i]+g.e[j].w) continue;
ru[v].push_back(i),tr.add(i,v);
}
}
}
namespace dt{
int ans,dep[N],pa[N][20],tot,head[N],siz[N],top[N],de[N];
node d[N<<1];
inline void Add(int u,int v){
dep[v]=dep[u]+1;
pa[v][0]=u;
for(int i=1;i<=19;++i) pa[v][i]=pa[pa[v][i-1]][i-1];
d[++tot].v=v;d[tot].nxt=head[u];head[u]=tot;
}
inline int LCA(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v];
for(int i=19;i>=0;--i) if(t&(1<<i)) u=pa[u][i];
if(u==v) return u;
for(int i=19;i>=0;--i) if(pa[u][i]!=pa[v][i]) u=pa[u][i],v=pa[v][i];
return pa[u][0];
}
inline void dfs(int u){
siz[u]=1;
for(int i=head[u];i;i=d[i].nxt){
int v=d[i].v;
if(v!=pa[u][0]) dfs(v),siz[u]+=siz[v];
}
if(u!=s) ans=max(ans,siz[u]);
}
inline void build(){
queue<int> q;
q.push(s);
for(int i=1;i<=n;++i) de[i]=ru[i].size();
while(!q.empty()){
int u=q.front();q.pop();
top[++tot]=u;
for(int i=tr.first[u];i;i=tr.e[i].nxt){
int v=tr.e[i].v;
if(!(--de[v])) q.push(v);
}
}
for(int i=2;i<=n;++i){
int u=top[i],lca=0;
for(int j=0;j<ru[u].size();++j){
int v=ru[u][j];
if(!lca) lca=v;
else lca=LCA(lca,v);
}
Add(lca,u);
}
dfs(s);
printf("%d\n",ans);
}
}
int main(){
n=read();m=read();s=read();
for(int i=1,u,v,w;i<=m;++i){
u=read();v=read();w=read();
g.add(u,v,w);g.add(v,u,w);
}
dijkstra();
dt::build();
return 0;
}