客观上说,这道题是并查集和01背包问题的基础题

#include<bits\stdc++.h>
using namespace std;
namespace mySTL{
    class UF{//real size is bigger
        private:
        int size;
        int *arr;
        int *weight;
        int num_sets;
        public:
        UF(int Nsize):size(Nsize),num_sets(Nsize){//in fact,realsize=1+Nsize
            arr=new int [size+1];//real size is bigger
            weight=new int [size+1];//tree root size
            for(int i=1;i<=size;++i){
                arr[i]=i;
                weight[i]=1;
            }
        }
        ~UF(){
            if(arr!=nullptr){
                delete[] arr;
            }
            if(weight!=nullptr){
                delete[] weight;
            }
        }
        int find(int i){
            int now=i;
            while(arr[now]!=now){//find root node
                now=arr[now];
            }//only index at root matters
            return now;
        }
        void connect(int i,int j){
            int iroot=find(i);
            int jroot=find(j);
            if(iroot!=jroot){
                --num_sets;//one of roots has been removed
                //determine which of roots to redirect
                if(weight[iroot]==weight[jroot]){
                    arr[iroot]=jroot;
                    weight[jroot]+=1;
                }else if(weight[iroot]<weight[jroot]){
                    arr[iroot]=jroot;
                }else{
                    arr[jroot]=iroot;
                }
            }
        }
        bool isSame(int i,int j){
            return find(i)==find(j);
        }
        int countSets(){
            return num_sets;
        }
    };
}
#define MAXMEN 10005
struct person{
    int cost,profit;
}peo[MAXMEN];

int inputAndGetAccess(int N,int M){
    for(int iN=2;iN<=N;++iN){
        cin>>peo[iN].cost>>peo[iN].profit;
    }
    mySTL::UF nowUF(N);
    int temx,temy;
    for(int iM=1;iM<=M;++iM){
        cin>>temx>>temy;
        nowUF.connect(temx,temy);
    }
    int newlen=0;
    peo[0]=peo[1];//change to make it easier.
    int root1=nowUF.find(1);
    for(int i=2;i<=N;++i){
        if(nowUF.find(i)==root1){
            peo[newlen++]=peo[i];
        }
    }
    return newlen;
}

#define MAXC 510
int dp[2][MAXC];
int _01back(int plen,int C){
    memset(dp,0xcf,sizeof(dp));
    dp[0][0]=0;
    for(int i=0;i<plen;++i){
        for(int jc=0;jc<=C;++jc){
            dp[(i+1)&1][jc]=dp[i&1][jc];
        }//copy now info 
        for(int mayPutIndex=peo[i].cost;mayPutIndex<=C;++mayPutIndex){
            if(dp[(i+1)&1][mayPutIndex]<dp[i&1][mayPutIndex-peo[i].cost]+peo[i].profit){
                dp[(i+1)&1][mayPutIndex]=dp[i&1][mayPutIndex-peo[i].cost]+peo[i].profit;
            }
        }
    }
    int ans=0;
    for(int j=0;j<=C;++j){
        if(ans<dp[plen&1][j]){
            ans=dp[plen&1][j];
        }
    }
    return ans;
}

int main(){
#ifdef LOCAL
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
    int T;
    cin>>T;
    while(T--){
        int N,M,C;
        cin>>N>>M>>C;
        int plen=inputAndGetAccess(N,M);
        //now become a 01 back problem
        int ans=_01back(plen,C);
        cout<<ans<<endl;
    }
}