CSU - 1580 NCPC2014 Outing(树形依赖+分组背包)

Outing

 

Input

 

Output

 

Sample Input

4 4
1 2 3 4

Sample Output

4



分组背包:

for 所有的组k
for v=V..0
for 所有的i属于组k
f[v]=max{f[v],f[v-c[i]]+w[i]}

 

有一辆能载客m的车,有n个人,然后第i个人上车的条件是第a[i]个人要上车,问最多能上几个。

显然,一个连通块至多含有一个环。每一块的价值范围在【环点,块点】之间,将每一块视为一组,从每组的范围中任取一值,组成不超过m的最大值。因此可转换成分组背包模型。

 

#include<bits/stdc++.h>
#define MAX 1005
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;

int pre[MAX],f[MAX],a[MAX],b[MAX],bb[MAX];
int dp[MAX];

int find(int x){
    return f[x]==x?x:f[x]=find(f[x]);
}
int dfs(int x,int be,int s){
    
    if(b[x]==1) return s;
    b[x]=1;
    return dfs(pre[x],be,s+1);
}
int main()
{
    int t,n,m,i,j,k;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        f[i]=i;
    }
    for(i=1;i<=n;i++){
        scanf("%d",&pre[i]);
        int fi=find(i),fx=find(pre[i]);
        if(fi!=fx){
            f[fi]=fx;
        }
    }
    memset(a,0,sizeof(a));
    for(i=1;i<=n;i++){
        memset(b,0,sizeof(b));
        a[i]=dfs(i,i,0);
    }
    memset(b,INF,sizeof(b));
    memset(bb,0,sizeof(bb));
    for(i=1;i<=n;i++){
        b[find(i)]=min(a[i],b[find(i)]);
        bb[find(i)]++;
    }
    memset(dp,0,sizeof(dp));
    for(i=1;i<=n;i++){
        if(b[i]!=INF){
            for(j=m;j>=0;j--){
                for(k=b[i];k<=bb[i];k++){
                    if(j-k<0) continue;
                    dp[j]=max(dp[j],dp[j-k]+k);
                }
            }
        }
    }
    printf("%d\n",dp[m]);
    return 0;
}

 

posted @ 2018-08-28 17:29  yzm10  阅读(275)  评论(0编辑  收藏  举报