zoukankan      html  css  js  c++  java
  • luogu P2726 [SHOI2005]树的双中心

    传送门

    强行安利->巨佬题解

    如果只有一个点贡献答案,那么答案显然是这棵树的带权重心,这个是可以(O(n))求的.一个(O(n^2))暴力是枚举两个集合之间的分界边,然后对这两个集合分别算答案,合并更新

    考虑优化此过程,一个结论是一棵树内,只有(size_i*2>size_{root})的点才有可能成为带权重心,并且这一类点个数不超过2个 不会证啊qwq,感性理解一下吧.所以每次枚举是哪条边为分界线,然后把树分成两部分,从每个树的根开始算答案,如果(size_i*2le size_{root})就停止

    注意要扣除下面子树对上面子树的(size)的贡献再做

    更多细节详见代码

    #include<bits/stdc++.h>
    #define LL long long
    #define il inline
    #define re register
    #define db double
    #define eps (1e-5)
    
    using namespace std;
    const int N=50000+10;
    il LL rd()
    {
      LL x=0,w=1;char ch=0;
      while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
      return x*w;
    }
    int to[N<<1],nt[N<<1],hd[N],tot=1;
    il void add(int x,int y)
    {
      ++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;
      ++tot,to[tot]=x,nt[tot]=hd[y],hd[y]=tot;
    }
    int n,fa[N],sz[N],de[N],g[N],fc[N],sc[N],no,ans=1<<30;
    void dfs(int x)
    {
      for(int i=hd[x];i;i=nt[i])
    	{
    	  int y=to[i];
    	  if(y==fa[x]) continue;
    	  fa[y]=x,de[y]=de[x]+1,dfs(y),sz[x]+=sz[y],g[x]+=g[y]+sz[y];
    	  if(sz[fc[x]]<=sz[y]) sc[x]=fc[x],fc[x]=y;
    	  else if(sz[sc[x]]<sz[y]) sc[x]=y;
    	}
    }
    void cal(int x,int nw,int size,int &an)
    {
      an=min(an,nw);
      int y=sz[fc[x]]<sz[sc[x]]||fc[x]==no?sc[x]:fc[x];
      if(sz[y]*2>size) cal(y,nw-sz[y]+size-sz[y],size,an);
    }
    void work(int x)
    {
      for(int i=hd[x];i;i=nt[i])
    	{
    	  int y=to[i];
    	  if(y!=fa[x])
    		{
    		  no=y;
    		  for(int xx=x;xx;xx=fa[xx]) sz[xx]-=sz[y];
    		  int aa=1<<30,bb=1<<30;
    		  cal(1,g[1]-g[y]-de[y]*sz[y],sz[1],aa),cal(y,g[y],sz[y],bb);
    		  for(int xx=x;xx;xx=fa[xx]) sz[xx]+=sz[y];
    		  ans=min(ans,aa+bb);
    		  work(y);
    		}
    	}
    }
    
    int main()
    {
      n=rd();
      for(int i=1;i<n;i++) add(rd(),rd());
      for(int i=1;i<=n;i++) sz[i]=rd();
      dfs(1),work(1);
      printf("%d
    ",ans);
      return 0;
    }
    
    
    
  • 相关阅读:
    点击图片显示原图
    SQL判断语句
    窗口淡入淡出效果
    判断两段时间之间的时间差
    软件行业发展趋势
    VSS客户端不能访问问题“unable to open user login file\\服务器项目管理目录\data\logedin\用户名.log ”
    鑫哥儿子顺利降生了!
    面向对象原则之单一职责原则实现
    PHP编码,乱码问题
    泛型中的default(T)
  • 原文地址:https://www.cnblogs.com/smyjr/p/9911989.html
Copyright © 2011-2022 走看看