1. 程式人生 > >Codeforces 757F. Team Rocket Rises Again

Codeforces 757F. Team Rocket Rises Again

ORC swap cin long long head rip n) typedef ems

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

Codeforces 757F. Team Rocket Rises Again