【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;
}
posted @ 2021-01-17 16:15  cjTQX  阅读(57)  评论(0编辑  收藏  举报