码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 757F. Team Rocket Rises Again

时间:2018-07-15 14:51:43      阅读:166      评论:0      收藏:0      [点我收藏+]

标签:type   树的定义   删除   cout   stdout   pen   its   open   最大化   

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

标签:type   树的定义   删除   cout   stdout   pen   its   open   最大化   

原文地址:https://www.cnblogs.com/Yuzao/p/9091665.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!