B-经商-NC14545(dp背包+并查集)

B-经商

题号:NC14545
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述 

小d是一个搞房地产的土豪。每个人经商都有每个人经商的手段,当然人际关系是需要放在首位的。

小d每一个月都需要列出来一个人际关系表,表示他们搞房地产的人的一个人际关系网,但是他的精力有限,对应他只能和能够接触到的人交际。比如1认识2,2认识3,那么1就可以接触3进行交际,当然1和2也可以交际。

小d还很精明,他知道他和谁交际的深获得的利益大,接下来他根据自己的想法又列出来一个利益表,表示他和这些人交际需要耗用多少精力,能够获得的利益值为多少。

小d想知道,他在精力范围内,能够获得的利益值到底是多少。

设定小d自己的编号为1.并且对应一个人的交际次数限定为1.

输入描述:

本题包含多组输入,第一行输入一个数t,表示测试数据的组数
每组数据的第一行输入三个数,N,M,C,表示这个人际关系网一共有多少个人,关系网的关系数,以及小d的精力值
接下来N-1行,每行两个数ai,bi。这里第i行表示和编号为i+1的人认识需要花费ai的精力,能够获得的利益值为bi。
再接下来M行,每行两个数x,y,表示编号为x的人能够和编号为y的人接触
t<=50
2<=N<=10000
1<=M<=10*N
1<=ai,bi<=10
1<=C<=500
1<=x,y<=N

输出描述:

输出包含一行,表示小d能够获得的最大利益值

示例1

输入

复制

1
5 3 7
5 10
3 2
4 3
1 100
1 2
2 3
1 4

输出

复制

10
//#include <bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<list>
#include<set>
#include<iomanip>
#include<cstring>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cassert>
#include<sstream>
#include<algorithm>
using namespace std;
const int mod=1e9+7;
typedef long long  ll;
#define ls (p<<1)
#define rs (p<<1|1)
#define mid (l+r)/2
#define over(i,s,t) for(register long long i=s;i<=t;++i)
#define lver(i,t,s) for(register long long i=t;i>=s;--i)
const int MAXN = 305;
const int INF = 0x3f3f3f3f;
const int N=5e4+7;
const int maxn=1e5+5;
const double EPS=1e-10;
const double Pi=3.1415926535897;
//inline double max(double a,double b){
//    return a>b?a:b;
//}
//inline double min(double a,double b){
//    return a<b?a:b;
//}
 
int xd[8] = {0, 1, 0, -1, 1, 1, -1, -1};
int yd[8] = {1, 0, -1, 0, -1, 1, -1, 1};
 
//void Fire(){
//    queue<node> p;
//    p.push({fx,fy,0});
//    memset(fire, -1, sizeof(fire));
//    fire[fx][fy]=0;
//    while(!p.empty()){
//        node temp=p.front();
//        p.pop();
//        for(int i=0;i<8;i++){
//            int x=temp.x+xd[i];
//            int y=temp.y+yd[i];
//            if(x<0||x>=n||y<0||y>=m||fire[x][y]!=-1){
//                continue;
//            }
//            fire[x][y]=temp.val+1;
//            p.push({x,y,temp.val+1});
//        }
//    }
//}
//int bfs(){
//    queue<node> p;
//    memset(vis, 0, sizeof(vis));
//    p.push({sx,sy,0});
//    while (!p.empty()) {
//        node temp=p.front();
//        vis[temp.x][temp.y]=1;
//        p.pop();
//        for(int i=0;i<4;i++){
//            int x=temp.x+xd[i];
//            int y=temp.y+yd[i];
//            if(x<0||x>=n||y<0||y>=m)  continue;
//            if(x==ex&&y==ey&&temp.val+1<=fire[x][y]) return temp.val+1;
//            if(vis[x][y]||temp.val+1>=fire[x][y]||a[x][y]=='#') continue;
//            p.push({x,y,temp.val+1});
//        }
//    }
//    return -1;
//}

//一维哈希
//int n;
//string s;
//int bas=131;
//typedef unsigned long long ull;
//const ull mod1=100001651;
//ull a[100010];
//ull Hash(string s){
//    ll ans=0;
//    for(int i=0;i<s.size();i++){
//        ans*=bas;
//        ans+=int(s[i]);
//        ans%=mod1;
//    }
//    return ans;
//}

//二维哈希
//using lom=unsigned long long ;
//const lom bas1=131,bas2=233;
//const int M=505;
//int n,m;
//char a[M][M];
//lom _hash[M][M];
//lom p1[M],p2[M];
//
//
//void init(){
//    p1[0]=1;
//    p2[0]=1;
//    for(int i=1;i<=505;i++){
//        p1[i]=p1[i-1]*bas1;
//        p2[i]=p2[i-1]*bas2;
//
//    }
//}
//void Hash(){
//    _hash[0][0]=_hash[0][1]=_hash[1][0]=0;
//    for(int i=1;i<=n;i++){    //前缀和
//        for(int j=1;j<=m;j++){
//            _hash[i][j]=_hash[i][j-1]*bas1+a[i][j]-'a';
//        }
//    }
//    for(int i=1;i<=n;i++){   //二维前缀和
//        for(int j=1;j<=m;j++){
//            _hash[i][j]+=_hash[i-1][j]*bas2;
//        }
//    }
//
//}


int n,m,c;
int a[1000010];
int b[1000010];
ll dp[1010];
int fa[1000010];
void init(){
    for(int i=0;i<=n;i++){
        fa[i]=i;
    }
}
int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
void Union(int x,int y){
    int xx=find(x);
    int yy=find(y);
    if(xx!=yy){
        fa[xx]=yy;
    }
}
int  main(){
    int t;
    cin>>t;
    while (t--) {
        memset(dp,0,sizeof(dp));
        cin>>n>>m>>c;
        init();
        for(int i=2;i<=n;i++){
            cin>>a[i]>>b[i];
        }
        for(int i=0;i<m;i++){
            int x,y;
            cin>>x>>y;
            Union(x,y);
        }
        for(int i=2;i<=n;i++){
            if(find(1)==find(i)){
                for(int j=c;j>=0;j--){
                    if(j-a[i]>=0){
                        dp[j]=max(dp[j],dp[j-a[i]]+b[i]);
                    }
                }
            }
        }
        cout<<dp[c]<<endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭晋龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值