• BZOJ1131 [POI2008]Sta 其他


    原文链接http://www.cnblogs.com/zhouzhendong/p/8081100.html


    题目传送门 - BZOJ1131


    题意概括

      给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大。


    题解

      嘻,这题不卡栈。

      假设以1为根

      先跑一遍dfs,算出每一个子树的节点数size,同时算出以1为根节点的深度和。

      然后再跑一遍dfs,这一回,我们就可以算答案了。

      假设我们要把树根从一条边的一个节点移向另一个节点,那么,这两个节点为根的答案差就是这条边两端的节点个数差。因为其中一个节点代表的子树上的节点都要多走一步到根,而另一边少走一步。这样就可以在O(n)的时间复杂度内solve这一题了。


    代码

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int N=1000005;
    struct Gragh{
    	int cnt,y[N*2],nxt[N*2],fst[N];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int n,size[N],ans;
    LL sum[N],res[N];
    void dfs1(int rt,int pre){
    	size[rt]=1,sum[rt]=0;
    	for (int i=g.fst[rt];i;i=g.nxt[i])
    		if (g.y[i]!=pre){
    			int s=g.y[i];
    			dfs1(s,rt);
    			size[rt]+=size[s];
    			sum[rt]+=sum[s];
    		}
    	sum[rt]+=size[rt]-1;
    }
    void dfs2(int rt,int pre){
    	res[rt]=res[pre]-size[rt]+(n-size[rt]);
    	if (!ans||res[rt]>res[ans]||(res[rt]==res[ans]&&rt<ans))
    		ans=rt;
    	for (int i=g.fst[rt];i;i=g.nxt[i])
    		if (g.y[i]!=pre)
    			dfs2(g.y[i],rt);
    }
    int main(){
    	g.clear();
    	scanf("%d",&n);
    	for (int i=1,a,b;i<n;i++){
    		scanf("%d%d",&a,&b);
    		g.add(a,b);
    		g.add(b,a);
    	}
    	dfs1(1,0);
    	ans=0;
    	res[0]=sum[1]+n;
    	dfs2(1,0);
    	printf("%d",ans);
    	return 0;
    }
    

      

  • 相关阅读:
    时间工时累加
    python读取mnist
    开始学习haskell
    pip升级所有packages
    ImportError: numpy.core.multiarray failed to import
    NumPy for MATLAB users
    Spyder
    初学ObjectiveC
    Matlab闭包
    ObjeciveC 内存管理
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ1131.html
Copyright © 2020-2023  润新知