很久很久没写题解了,哈哈哈哈哈哈
核心算法并查集,01背包问题
刚开始做的时候我没看过01背包,只好去现学01背包问题。
题意:
商人,自古都是利益为先,所以本题中的商人自然想赚的更多,但是呢商人和不认识的人又不能进行交涉(可能比较害羞吧),只能和认识的人或者<认识的人>认识的人...交流,这时候应该很容易联想到并查集,让能交流的人都在同一个集合中。
首先是并查集的find(x);用于查找是否在同一个集合

int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);//三目运算符真的很香
}

然后合并:

void merge(int x,int y){
    fa[find(x)]=find(y);
}

并查集之后呢就是一个单纯的01背包问题,不过需要考虑的只有与老板在同一个集合中的元素;
所以需要在dp中加上一个条件;

    if(find(i)==find(1))

只有满足这个条件的人才能被老板利用(利用会不会太阴险,管他呢,哈哈哈哈)
贴上ac代码

#include<iostream>
#include<string.h>
using namespace std;
#define N 1000000
int dp[N];
int fa[N];
struct node{
    int pay;
    int get;
} peaple[100000];//我用的结构体存一个用户的花费与价值,其实可以分成两个数组存的;
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void merge(int x,int y){
    fa[find(x)]=find(y);
}
int main(){
    int T;
    cin>>T;
    while(T--){
        int m,n,c;
        cin>>n>>m>>c;
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=2;i<=n;i++){
            cin>>peaple[i].pay>>peaple[i].get;
        }
        int x,y; 
        for(int i=1;i<=m;i++){
        cin>>x>>y;
        merge(x,y); 
        } 
        memset(dp, 0, sizeof(dp));//T组输入记得初始化
        for(int i=2;i<=n;i++){
            if(find(i)==find(1)){
                for(int j=c;j>=peaple[i].pay;j--){
                    dp[j]=max(dp[j],dp[j-peaple[i].pay]+peaple[i].get);
                }
            }
        }
        cout<<dp[c]<<endl;
    }
    return 0;
}