poj 1947

树状DP+背包过的,得到的子树可以不包括根节点。写的垃圾,跑了600MS+。。。。

#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=155;
int first[maxn],vis[maxn],dp[maxn][maxn][2],in[maxn],f[maxn];
int N,P,size;
struct Edge
{
 int v,next;
}edge[maxn];
void insert(int u,int v)
{
 edge[size].v=v;
 edge[size].next=first[u];
 first[u]=size++;
}
void init()
{
 memset(in,0,sizeof(in));
 memset(first,-1,sizeof(first)); size=0;
 for(int i=0;i<maxn;i++)
  for(int j=0;j<maxn;j++)
   dp[i][j][0]=dp[i][j][1]=maxn;
}
void dfs(int u)  
{
 if(first[u]==-1)
 {
  dp[u][1][1]=0;
  return ;
 }
 int sub[maxn],cnt=0;
 for(int e=first[u];e!=-1;e=edge[e].next)
 {
  int v=edge[e].v; sub[cnt++]=v;
  dfs(v);
  for(int j=1;j<=P;j++)
   dp[u][j][0]=min(min(dp[v][j][1]+1,dp[v][j][0]),dp[u][j][0]);
 }
 for(int C=1;C<=P;C++)
 {
  for(int i=0;i<=P;i++) f[i]=maxn;
  f[0]=0;
  for(int i=0;i<cnt;i++)
  {
   int v=sub[i];
   for(int c=C-1;c>=0;c--)
    for(int j=1;j<=P;j++)
     if(c-j>=0) f[c]=min(f[c],f[c-j]+dp[v][j][1]-1);
  }
  dp[u][C][1]=f[C-1]+cnt;
 }
}
int main()
{
// freopen("test.txt","r",stdin);
 scanf("%d%d",&N,&P);
 init();
 for(int i=0;i<N-1;i++)
 {
  int u,v;
  scanf("%d%d",&u,&v);
  insert(u,v); in[v]=1;
 }
 for(int u=1;u<=N;u++)
  if(!in[u])
  { 
   dfs(u);
   printf("%d\n",min(dp[u][P][0],dp[u][P][1]));
   break;
  }
 return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值