【dp每一天】POJ

来源:互联网 发布:淘宝网抹胸连衣裙 编辑:程序博客网 时间:2024/05/17 22:04

额这题也挺水的。

题意:找树上满足去掉它之后,剩余连通的结点块中最大的那一块最小的结点们。

思路:有 dp[u] = max(sum[v], n - sum[u]); v是u的子结点

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 5e4 + 10,maxe = maxn * 2;const int inf = 0x3f3f3f3f;struct node{    int to,next;    node(){}    node(int a,int b){to = a ; next = b;}}edge[maxe];int h[maxn],sum[maxn];int num,n,anum;int ans[maxn];int vans = inf;void init(){    for(int i = 0; i <= n; i++)        h[i] = -1, sum[i] = 0;    num = 0;    anum = 0;   vans = inf;}void add(int u,int v){    edge[num] = node(v,h[u]);    h[u] = num++;}void solve(int u,int pre){    int res = 0,cnt = 0;    for(int i = h[u] ;~i ; i = edge[i].next)    {        int v = edge[i].to;        if(v == pre) continue;        solve(v,u);        cnt += sum[v];        res = max(sum[v],res);    }    sum[u] = cnt + 1;    res = max(res,n-sum[u]);    if(res < vans)    {        anum = 0;        vans = res;        ans[anum++] = u;    }    else if(res == vans)        ans[anum++] = u;}int main(){    while(~scanf("%d",&n))    {        init();        int a,b;        for(int i = 0; i < n-1; i++)        {            scanf("%d%d",&a,&b);            add(a,b);   add(b,a);        }        solve(1,-1);        sort(ans,ans+anum);        for(int i = 0; i < anum; i++)            i==0?printf("%d",ans[i]) : printf(" %d",ans[i]);        printf("\n");    }    return 0;}


原创粉丝点击