SZOJ 142 钦定

太暴力了QAQ

题目描述
现在有n个人,每个人有责任度bi和影帝度wi,要从中钦定一个长老团

我们知道,一个好的长老团,他的责任度要越高越好,而为了防止_____,影帝度则不能超过给定的WW
此外,这些人之间有着奥妙穷穷的m条关系,具体来说就是m条xi和yi之间的关系

而如果x和y有关系y和z有关系,那么x和z也有关系,有关系的人分成一组的话,这些关系把n个候选人分成了若干组

为了保证关系的稳定,每一组中的人,要么全部被选入长老团,要么最多只能有一个人进入长老团

现在,请问这个长老团的责任度最高是多少

输入格式
输入3个整数n, m和w表示人数,关系数和影帝度上限

第二行包含n个数wi
第三行包含n个数bi
接下来m行每行两个整数xi,yi表示xi和yi之间有关系

输入样例
3 1 5
3 2 5
2 4 2
1 2
输出样例
6
样例解释
选1,21,2得到w=3+2=5, b=2+4=6
数据规模
对于20%的数据,1≤n≤18
对于100%的数据,1≤n≤1000, 1≤w≤1000, 1≤wi≤1000, 1≤bi≤106
关系是双向的,并且不会重复

这是一道背包问题,我们再考虑放入每组最优的同时也要尝试放入整组,由于人与人之间的关系,还是用个vector简单一些,注意范围中 bi>=1,所以不滚动直接dp是OK的(然而原本出的数据出现了偏差),而如果存在bi==0,那么我们只要把数组滚动就好了

别滚苟了。。。(滚苟的路过)

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
int n,m,w,fa[1001],dp[1001][2];
struct node{
    int x,y;
}e[1001];
vector <int> v[1001];
inline int find(int a){
    if(fa[a]!=a) return fa[a]=find(fa[a]);
    return a;
}
inline void Jimmy(){
    scanf("%d%d%d",&n,&m,&w);
    for(int i=1;i<=n;i++){
        scanf("%d",&e[i].x);
        fa[i]=i;
    }
    for(int i=1;i<=n;i++)
        scanf("%d",&e[i].y);
    for(int i=1,a,b;i<=m;i++){
        scanf("%d%d",&a,&b);
        int fx=find(a),fy=find(b);
        if(fx!=fy) fa[fx]=fy;
    }
    for(int i=1;i<=n;i++)
        v[find(i)].push_back(i);
    for(int i=1;i<=n;i++)
        if(find(i)==i){
            for(int j=w;j>=1;j--){
                int numa=0,numb=0;
                for(int k=0;k<v[i].size();k++){
                    numa+=e[v[i][k]].x;
                    numb+=e[v[i][k]].y;
                    if(j>=e[v[i][k]].x)
                        dp[j][1]=max(dp[j][1],dp[j-e[v[i][k]].x][0]+e[v[i][k]].y);
                }
                if(j>=numa)
                    dp[j][1]=max(dp[j][1],dp[j-numa][0]+numb);
                dp[j][0]=max(dp[j][0],dp[j][1]);
            }
        }
    printf("%d",dp[w][1]);    
}
int main(){
    Jimmy();
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/JimmyC/p/6503172.html