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

Codeforces Round #322 (Div. 2)

时间:2015-09-29 01:09:32      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:

F. Zublicanes and Mumocrates 树形dp

题意给了一棵树 要求使得这棵树所有的节点分为两个阵营,其中叶子节点要均分,求最少的两个阵营相邻, 也就是求 最少的边使得 这些边两头阵营不同 

dp[cur][i][j] 表示当cur为i阵营的时候 有j个和i同阵营的方案

dp[cur][i][j+k] = min{dp[to][i^1][j=(叶子个数-d)]+dp[cur][i][k]+1,dp[to][i][j]+dp[cur][i][k]}

cnt为叶子节点的个数 最后答案是 min{ dp[root][0][cnt/2] ,dp[root][1][cnt/2]}

技术分享
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=5005;
int H[maxn],to[maxn*2],nx[maxn*2],numofE;
void add(int u, int v)
{
     numofE++;
     to[numofE]=v;
     nx[numofE]=H[u];
     H[u]=numofE;
}
int dp[maxn][2][maxn];
int dp2[2][maxn],sz[maxn];
int d[maxn];
void dfs(int cur ,int per)
{
      if(d[cur]==1){
         sz[cur]=1;
         dp[cur][0][1]=dp[cur][1][1]=0;
         return ;
      }
      dp[cur][0][0]=dp[cur][1][0]=0;
      for(int i=H[cur]; i ; i=nx[i])
        {
              int tto = to[i];
              if(tto==per)continue;
               dfs(tto,cur);
             for(int i=0; i<=sz[cur]; i++)
                 for(int u=0; u<2; u++)
                  {
                      if( dp[cur][u][i] == -1 ) continue;

                      for(int j=0; j<=sz[tto]; j++)
                      for(int v=0; v<2; v++)
                        {
                            if(dp[tto][v][j]==-1)continue;
                            if(u==v)
                            {
                                if(dp2[u][i+j]==-1)
                                {
                                     int k=dp[cur][u][i]+dp[tto][v][j];
                                    dp2[u][i+j] = k;

                                }else {
                                      int k=min(dp[cur][u][i]+dp[tto][v][j],dp2[u][i+j]);
                                    dp2[u][i+j]=k;

                                }
                            }else
                            {
                                int nu=sz[tto];
                                if(dp2[u][i+nu-j]==-1)
                                   {
                                       int k=dp[cur][u][i]+dp[tto][v][j]+1;
                                       dp2[u][i+nu-j]=k;
                                   }
                                else
                                    {
                                    int k=min(dp[cur][u][i]+dp[tto][v][j]+1,dp2[u][i+nu-j]);
                                    dp2[u][i+nu-j]=k;

                                    }
                            }
                        }
                  }
             sz[cur]+=sz[tto];
             for(int i=0; i<=sz[cur]; i++)
                for(int j=0; j<2; j++)
                {
                      dp[cur][j][i]=dp2[j][i];
                      dp2[j][i]=-1;
                }
        }
}
int main()
{
    int n;
    while(scanf("%d",&n)==1)
        {
             memset(d,0,sizeof(d));
             memset(dp,-1,sizeof(dp));
             memset(sz,0,sizeof(sz));
             memset(dp2,-1,sizeof(dp2));
             memset(H,0,sizeof(H));
             numofE=0;
            for(int i=1; i<n; i++)
                {
                    int a,b;
                    scanf("%d%d",&a,&b);
                    add(a,b);
                    add(b,a);
                    d[a]++;d[b]++;
                }
            if(n==2){
                printf("%d\n",1); continue;
            }
            int root;
            int cnt=0;
            for(int i=1; i<=n; i++){
                if(d[i]==1)cnt++;
                else root=i;
            }
            dfs(root,-1);
            printf("%d\n",min(dp[root][0][cnt/2],dp[root][1][cnt/2]));
        }
    return 0;
}
/*
6
1 2
2 5
2 3
3 4
3 6
*/
View Code

 

Codeforces Round #322 (Div. 2)

标签:

原文地址:http://www.cnblogs.com/Opaser/p/4845287.html

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