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; }