zoukankan      html  css  js  c++  java
  • 洛谷P2195

    Double!

    Description

    要求完成两种操作:

    • 查询一个点所在树的直径;
    • 添加一条边合并两个点所在的树,要求合并后新树的直径最小。

    Solution

    显然我们无法每次真的合并两棵树再重新跑一遍直径,那我们看一下树的合并有什么特殊的性质。

    通过手玩几个简单的样例我们可以发现,直径为 (x) 的树与直径为 (y) 的树合并后形成的新树直径为 (max{x,y,lceil frac{x}{2} ceil+lceil frac{y}{2} ceil+1})

    因为要保证新树直径最小,那我们肯定会连接两棵树的直径的中点。

    若两棵树的直径 (x>y),那我们连接后可以发现,新树的直径大小仍然是 (x)(x<y) 时同理为 (y)

    若两棵树的直径 (x=y),那我们连接后可以发现,新树的直径大小为
    (lceil frac{x}{2} ceil+lceil frac{y}{2} ceil+1)

    因为在长度不同时前者大于后者,长度相同时后者大于前者。所以三者直接去最大值即可。

    我们先求出初始的森林中每棵树的直径,合并与判断操作靠并查集实现,然后更新所在树的直径即可。

    int n,m,q,tot,len,sec;
    int head[maxn],fa[maxn];
    int ans[maxn],Dis[maxn];
    struct edge{int fr,to,nxt;}e[maxn<<1];
    
    void add(int fr,int to){
      e[++tot]=(edge){fr,to,head[fr]};
      head[fr]=tot;
    }
    
    int findf(int x){
      return fa[x]^x?fa[x]=findf(fa[x]):x;
    }
    
    void dfs(int u,int fat){
      Dis[u]=Dis[fat]+1;
      if(Dis[u]>len)len=Dis[u],sec=u;
      for(int i=head[u];i;i=e[i].nxt){
        int to=e[i].to;
        if(to==fat) continue;
        dfs(to,u);
      }
    }
    
    int main(){
      n=read();m=read();q=read();
      for(int i=1;i<=n;i++) fa[i]=i;
      for(int i=1,fr,to,dis;i<=m;i++){
        fr=read();to=read();
        add(fr,to);add(to,fr);
        fr=findf(fr),to=findf(to);
        if(fr!=to) fa[to]=fr;
      }
      for(int i=1;i<=n;i++){
        if(findf(i)!=i) continue;
        dfs(i,0);len=0;dfs(sec,0);
        ans[i]=len-1;len=0;sec=0;
      }
      for(int i=1,opt,x,y;i<=q;i++){
        opt=read();x=read();
        if(opt==1) printf("%d
    ",ans[findf(x)]);
        else{
          y=read();x=findf(x);y=findf(y);if(x==y) continue;fa[y]=x;
          ans[x]=max(max(ans[x],ans[y]),(ans[x]+1)/2+(ans[y]+1)/2+1);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    第十二天
    php获取变量所占内存大小的方法
    php数组倒序
    最近学习时遇到的一些函数
    php curl发送留言实例
    php性能测试
    php敏感字过滤替换
    php常用函数
    必学PHP类库/常用PHP类库大全
    thinkphp html转为字符
  • 原文地址:https://www.cnblogs.com/KnightL/p/15480958.html
Copyright © 2011-2022 走看看