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

poj1655(dfs,树形dp)

时间:2014-08-08 04:16:45      阅读:237      评论:0      收藏:0      [点我收藏+]

标签:style   blog   color   os   io   for   ar   div   

方法:就记节点1为树的根,两次dfs,第一次求出每个节点的所有子孙再加上它自己的节点总数num[i]。第二次就算出每个节点的balance值bal[i],算的时候就比较节点i它所有子节点的num值(删掉它之后以每个它的子节点为根形成一棵新树)还有n-num[i]的值(删掉i之后它的父节点及其相关节点也形成一棵新树),最大的就是bal[i]。

注意:WA了几次是因为没有考虑边界情况(n==2),dfs写的太不熟练了,代码能力有待提高啊!

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<stack>
#include<queue>
using namespace std;
#define INF 1000000000
#define eps 1e-8
#define pii pair<int,int>
#define LL long long int
int T,n,a,b,ans_i,ans;
vector<int>v[20005];
int num[20005],bal[20005];
int dfs1(int i,int fa);
void dfs2(int i,int fa);
int main()
{
    //freopen("in2.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        ans_i=0;
        ans=INF;
        scanf("%d",&n);
        if(n==1)
        {
            printf("1 0\n");
        }
        else if(n==2)
        {
            scanf("%d%d",&a,&b);
            printf("1 1\n");
        }
        else
        {
            for(int i=1; i<=n; i++)
            {
                v[i].clear();
                num[i]=1;
                bal[i]=-1;
            }
            for(int i=1; i<n; i++)
            {
                scanf("%d%d",&a,&b);
                v[a].push_back(b);
                v[b].push_back(a);
            }
            dfs1(1,-1);
            dfs2(1,-1);
            for(int i=1; i<=n; i++)
            {
                if(bal[i]<ans)
                {
                    ans_i=i;
                    ans=bal[i];
                }
            }
            printf("%d %d\n",ans_i,ans);
        }
    }
    //fclose(stdin);
    //fclose(stdout);
    return 0;
}
int dfs1(int i,int fa)
{
    /*if(v[i].size()==1)
        return num[i];*/
    /*这句判断是不能加的,加了就是WA,个中原因非常微妙:
    因为我加这句的本意是当遇到了叶子节点时,它的num就直接返回1就行了,
    而叶节点的size就是1(只有父节点)。
    但是我这里就忽略了一种特殊情况,那就是这棵数可能根节点的size也为1!!!
    所以就在这种情况下WA了。
    实际上没有必要加这一句,下面的循环语句已经可以很好的处理各个节点了。*/
    //这里可以总结一条树的性质:叶节点一定含一条边,根节点可能含一条边,其它节点至少含两条边。
    for(unsigned int j=0; j<v[i].size(); j++)
    {
        int &t=v[i][j];
        if(t==fa)
        {
            continue;
        }
        else
        {
            num[i]+=dfs1(t,i);
        }
    }
    //cout<<i<<"_-_"<<num[i]<<endl;
    return num[i];
}
void dfs2(int i,int fa)
{
    for(unsigned int j=0; j<v[i].size(); j++)
    {
        int &t=v[i][j];
        if(t==fa)
        {
            bal[i]=max(bal[i],num[1]-num[i]);
        }
        else
        {
            bal[i]=max(bal[i],num[t]);
            dfs2(t,i);
        }
    }
    //cout<<i<<"___"<<bal[i]<<endl;
}

 

poj1655(dfs,树形dp),布布扣,bubuko.com

poj1655(dfs,树形dp)

标签:style   blog   color   os   io   for   ar   div   

原文地址:http://www.cnblogs.com/zywscq/p/3898490.html

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