poj 3107Godfather 树型dp或者dfs(简单的树的操作)

题目:poj 3107Godfather

题意:给定一棵无根树,删除树中一个节点,使得剩下各子树的包含的节点数最大值最小,问树中有多少个这样的节点? 然后字典序输出。

解题:遍历一遍所有节点就可以了。很简单,但是TLE了一上午,原因就是数据很变态吧,卡STL(可能是自己用的不熟练吧),然后自己写一个就直接AC了。

代码如下:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 50001
#define Max (1<<(31)-1)
struct Node{
    int v,next;
}arcnode[N*2];

int vnode[N],v_dp[N],ans[N];
int ans_num,ans_key,k,num;
bool vist[N];

void Addedge(int u,int v)
{
    arcnode[k].v=v;
    arcnode[k].next=vnode[u];
    vnode[u]=k++;
}

void dfs(int key)
{
    vist[key]=false;
    v_dp[key]=1;
    int i,v,maxx=-1;
    for(i=vnode[key];i;i=arcnode[i].next)
    {
        v=arcnode[i].v;
        if(!vist[v]) continue;
        dfs(v);
        v_dp[key]+=v_dp[v];
        maxx=max(maxx,v_dp[v]);
    }
    maxx=max(maxx,num-v_dp[key]);
    if(maxx==ans_key)
        ans[ans_num++]=key;
    if(maxx<ans_key)
    {
        ans_num=0;
        ans[ans_num++]=key;
        ans_key=maxx;
    }
}

int main()
{
    while(~scanf("%d",&num))
    {
        int i,a,b;
        k=1;ans_num=0;ans_key=num;
        memset(vist,true,sizeof(vist));
        memset(vnode,0,sizeof(vnode));
        for(i=1;i<num;i++)
        {
            scanf("%d%d",&a,&b);
            Addedge(a,b);            Addedge(b,a);
        }
        dfs(1);
        sort(ans,ans+ans_num);
        for(i=0;i<ans_num;i++)
        {
            printf("%d",ans[i]);
            if(i!=ans_num-1)            putchar(' ');
            else            puts("");
        }
    }
}


你可能感兴趣的:(poj 3107Godfather 树型dp或者dfs(简单的树的操作))