传送门
先用并查集将其集合化,然后寻找与1一个集合的所有人。
因为每个人只可以使用一次,所以在dp的循环中,把人数的循环放在外面。
#include<bits/stdc++.h>
using namespace std;
const int MX=1e4+9;
int T,n,m,c,fa[MX],u,v,k,t[MX],ans;
struct node{
int hp=0,val=0;
}peo[MX],use[MX];
int fin(int u){
return fa[u]=(fa[u]==u?u:fin(fa[u]));
}
void link(int u,int v){
u=fin(u);
v=fin(v);
if( u!=v ){
if( u<v )
fa[v]=u;
else
fa[u]=v;
}
}
int main()
{
// freopen("input.txt","r",stdin);
scanf("%d",&T);
while( T-- ){
memset(t,0,sizeof(t));
memset(use,0,sizeof(use));
memset(peo,0,sizeof(peo));
scanf("%d %d %d",&n,&m,&c);
for( int i=1 ; i<=n ; i++ )
fa[i]=i;
for( int i=2 ; i<=n ; i++ )
scanf("%d %d",&peo[i].hp,&peo[i].val);
for( int i=1 ; i<=m ; i++ ){
scanf("%d %d",&u,&v);
link(u,v);
}
k=0,ans=0;
for( int i=2 ; i<=n ; i++ )
if( fin(i)==1 )
use[++k]=peo[i];
for( int i=1 ; i<=k ; i++ ) // 把人数的循环放在外面
for( int j=c ; j>=use[i].hp ; j-- )
t[j]=max(t[j],t[j-use[i].hp]+use[i].val);
printf("%d\n",t[c]);
}
return 0;
}