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;
}

posted @ 2018-07-15 13:49  PIPIBoss  阅读(261)  评论(0编辑  收藏  举报