poj 1655

这道题我有很多要说

首先是基础的解题思路:

树形dp(dfs)用dp[i]保存以i为根结点的子树的大小(含i)

balance(i)=max{n-dp[i],max{dp[j]}(j is a son of i}

O(n)

这题我RE了5次,WA了5次,AC来之不易啊

反观10次unACs(我承认是我创的,自己能看懂),发现只有一个问题:

清零

短短3行字,调了我2小时!!!以后注意吧。。。

吐槽多了,赶快上代码:

#include<cstdio>

#include<cstring>

using namespace std;

int n,dp[20100],to[40100],top,next[40100],first[20100];

int min=1<<20,ans=-1;

bool vis[20100]={0};

void solve(int i){

         dp[i]=1;vis[i]=1;

         int cur=0;

         for(int j=first[i];j!=-1;j=next[j])if(!vis[to[j]]){

                   solve(to[j]);

                   if(dp[to[j]]>cur)cur=dp[to[j]];

                   dp[i]+=dp[to[j]];

         }

         if(n-dp[i]>cur)cur=n-dp[i];

//      printf("%d %d\n",i,cur);

         if(cur<min || cur==min && i<ans){

                   min=cur;

                   ans=i;

         }

         return;

}

int main(){

         int t;

         scanf("%d",&t);

         while(t--){

                   min=1<<20;ans=-1;                   //没打时WA

                   top=0;                             //没打时RE

                   memset(first,-1,sizeof(first));

                   memset(vis,0,sizeof(vis));             //没打时WA

                   memset(dp,0,sizeof(dp));             //可打可不打

                   scanf("%d",&n);

                   for(int i=1;i<n;i++){

                            int x,y;

                            scanf("%d%d",&x,&y);

                            x--;y--;

                            to[top]=y;

                            next[top]=first[x];first[x]=top++;

                            to[top]=x;

                            next[top]=first[y];first[y]=top++;

                   }

                   solve(0);

                   printf("%d %d\n",ans+1,min);

         }

         return 0;

}

原文地址:https://www.cnblogs.com/shanquan2/p/3168582.html