列表

详情


NC200584. 集训队的依赖关系

描述

    众所周知,SMU算法竞赛团队存在着极其复杂的内部依赖关♂系,这个依赖关系体现在每次决定是否出去吃饭的时候。某个周六中午,大家相约一起去吃自助,却忘记叫队长一起去了。下午训练结束了到了吃饭的时间,队长问大家一句:吃饭吗?大家刚吃完自助很饱,其实都不想去,但是又不好意思直接说出口,于是开始耍花招:磊子哥说,杰去我就去;琛说,佳佳文去我就去;玮说,琛去我就去……

    为了不让队长生气,每个人至多只能依赖一个人,但是一个人可以被多个人依赖。

    在队长的心里,和每个人去吃饭都有一个期待值,一个人和队长一起去吃饭了,队长就能得到对应的期待值。而劝导一个人去吃饭会有一定的花费,比如杰是一个富 有 原 则 性的人,除非你给他5元或5元以上的钱,否则他是绝对不会一起去的。现在队长有S元钱,告诉你队长对于每个人的期待值以及劝导他去吃饭的最小花费,队长想知道在花费不超过S元的前提下,他能获得的最大期待值。值得注意的是,队长要劝导一个人去吃饭,必须先劝导他依赖的人去吃饭(如果有的话)。(换言之,u依赖v,要劝导u去吃饭,必须先劝导v)。另外,如果依赖关系构成了一个环(比如1依赖2,2依赖3,3依赖1),队长会感觉自己受到了侮辱,所以不会劝导这个环的任何一个人


输入描述

第一行两个整数,分别代表集训队的人数,队长的总钱数,以及集训队的依赖关系数。
第二行n个整数val_1, val_2, ..., val_n,其中代表第i个人的期待值
第三行n个整数cost_1, cost_2, ..., cost_n,其中代表劝导第i个人的最小花费
第四行至第m+3行,每行两个整数u v, 代表第u个人依赖第v个人。   保证每个人至多依赖一个人。

输出描述

输出一个整数,表示队长在花费不超过S的情况下能获得的最大期待值

示例1

输入:

3 100 2
1 1 1
2 2 2
2 1
3 1

输出:

3

说明:

三个人都可以劝导,获得的总期待值就是3

示例2

输入:

2 100 2
1 1
2 2
1 2
2 1

输出:

0

说明:

构成环啦,都不会劝导,所以答案是0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 217ms, 内存消耗: 196560K, 提交时间: 2019-12-30 11:49:05

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e3+5;
vector<int> G[N];
int n,m,s,val[N],cost[N],in[N];
ll f[N][N];
void dfs(int u,int fa) {
	for(int i=s;i>=cost[u];i--) {
		f[u][i]=f[u][i-cost[u]]+val[u];
	}
	for(int i=0;i<cost[u];i++) f[u][i]=-1e18;
    for(int i=0;i<G[u].size();i++) {
        int v=G[u][i];
        if(v==fa) continue;
        for(int j=0;j<=s;j++) f[v][j]=f[u][j];
    	dfs(v,u);
        for(int j=0;j<=s;j++) f[u][j]=max(f[u][j],f[v][j]);
    }  
}
int main() {
    scanf("%d%d%d",&n,&s,&m);
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
    for(int i=0,u,v;i<m;i++) {
        scanf("%d%d",&u,&v);
        G[v].push_back(u);
        in[u]++;
    }
    for(int i=1;i<=n;i++) {
    	if(!in[i]) G[0].push_back(i);
    }
    dfs(0,-1);
    ll ans=0;
    for(int i=0;i<=s;i++) {
        ans=max(ans,f[0][i]);
    }
    printf("%lld\n",ans);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 38ms, 内存消耗: 47340K, 提交时间: 2019-12-29 22:56:15

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e3+10;
vector<int> mp[N];
ll dp[N][N],val[N],cost[N];
int indeg[N],n,s,m,x,y;
void dfs(int x,int sum){sum+=cost[x];
    for(int y:mp[x]){for(int i=sum+cost[y];i<=s;++i)dp[y][i]=dp[x][i-cost[y]]+val[y];dfs(y,sum);
        for(int i=sum+cost[y];i<=s;++i)dp[x][i]=max(dp[x][i],dp[y][i]);}
}
int main(){
    scanf("%d%d%d",&n,&s,&m);
    for(int i=1;i<=n;++i)scanf("%lld",val+i);
    for(int i=1;i<=n;++i)scanf("%lld",cost+i);
    while(m--){scanf("%d%d",&x,&y);mp[y].push_back(x);++indeg[x];}
    for(int i=1;i<=n;++i)if(!indeg[i])mp[0].push_back(i);
    dfs(0,0);printf("%lld",dp[0][s]);
    return 0;
}

上一题