zoukankan      html  css  js  c++  java
  • 树的重心

    先看题:P1395会议

    树的重心,就是在一棵树中拆掉一个点,把这棵树分成几个部分,使得最大的部分最小,亦即拆得均匀,这个拆掉的点就是树的重心。

    那么怎么求呢?我们可以从根结点开始dfs(什么?你说是无根树。那就定义节点1为根呗),返回值是这棵子树的大小。然后定义一个(mx)(mx=max{dfs( ext{该结点的子结点的})}) 。最后,在枚举完子节点后,再判断他父亲那一块的大小。然后记录值。
    现在唯一的问题就是父亲那块怎么解决呢?没错,用总结点数减去这棵子树的大小,就是他父亲那一块的大小。

    现在来解决第二问 ,这问其实可以在解决树的重心后直接dfs或bfs,然后就可以得出总的路程了。这一块就不用详细解释了。

    上代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,ans=50005,sum=50005,road;//n是总结点数,ans是树的重心的编号,sum是其最那块的大小,road是总路程
    int t[50005];//ti表示结点i到ans的距离。
    queue<int>q;//q用来后面bfs用
    struct graph
    {
    	int tot;
    	int dt[100005],nxt[100005];
    	int hd[50005];
    	void add(int x,int y)
    	{
    		tot++;
    		nxt[tot]=hd[x];
    		hd[x]=tot;
    		dt[tot]=y;
    	}
    }g;//graph是链式前向星。
    int dfs(int x,int fa)
    {
    	int k=0;//k代表其所以子树的大小
    	int mx=0;//mx是将这个点拆掉后最大那块的大小
    	for(int i=g.hd[x];i;i=g.nxt[i])//遍历所以点子节点
    	 if(g.dt[i]!=fa)//注意判该节点是否是x的父亲,不判会爆栈的
    	 {
    	 	int xx=dfs(g.dt[i],x);//记录这棵子树的大小
    		k+=xx;//加上这棵子树的大小
    		mx=max(mx,xx);//取最大值
    	 }
    	mx=max(mx,n-k-1);//最后判一下父亲那块,最后的-1是因为最开始没有把自己算进去
    	if(mx<sum||(mx==sum&&x<ans)) sum=mx,ans=x;//如果比当前方案更优,就取这个方案
    	return k+1;//返回整棵子树的大小
    }
    void bfs()
    {
    	q.push(ans);//记录最初的点
    	while(!q.empty())//如果队列不为空
    	{
    		int xx=q.front();//记录队首
    		q.pop();//弹出队首
    		for(int i=g.hd[xx];i;i=g.nxt[i])//遍历链接它的节点
    		{
    			int yy=g.dt[i];
    			if(t[yy]||yy==ans) continue;//如果这个点已经被遍历过,continue
    			t[yy]=t[xx]+1;//记录距离
    			road+=t[yy];//总距离要加上这个点的距离
    			q.push(yy);//放进队列
    		}
    	}
    	return ;
    }
    int main()
    {
    	cin>>n;
    	for(int i=1;i<n;i++)
    	{
    		int from,to;
    		cin>>from>>to;
    		g.add(from,to);
    		g.add(to,from);
    	}//输入+存图,注意是双向边
    	dfs(1,0);//dfs,把1的父亲设为0,就是没有父节点了(因为没有节点0)
    	bfs();//求出树的重心后,求总路程
    	cout<<ans<<' '<<road;
    	return 0;
    }
    
  • 相关阅读:
    动态规划——Best Time to Buy and Sell Stock IV
    动态规划——Split Array Largest Sum
    动态规划——Burst Ballons
    动态规划——Best Time to Buy and Sell Stock III
    动态规划——Edit Distance
    动态规划——Longest Valid Parentheses
    动态规划——Valid Permutations for DI Sequence
    构建之法阅读笔记05
    构建之法阅读笔记04
    构建之法阅读笔记03
  • 原文地址:https://www.cnblogs.com/mk-oi/p/13522653.html
Copyright © 2011-2022 走看看