NC200584. 集训队的依赖关系
描述
众所周知,SMU算法竞赛团队存在着极其复杂的内部依赖关♂系,这个依赖关系体现在每次决定是否出去吃饭的时候。某个周六中午,大家相约一起去吃自助,却忘记叫队长一起去了。下午训练结束了到了吃饭的时间,队长问大家一句:吃饭吗?大家刚吃完自助很饱,其实都不想去,但是又不好意思直接说出口,于是开始耍花招:磊子哥说,杰去我就去;琛说,佳佳文去我就去;玮说,琛去我就去……
为了不让队长生气,每个人至多只能依赖一个人,但是一个人可以被多个人依赖。
在队长的心里,和每个人去吃饭都有一个期待值,一个人和队长一起去吃饭了,队长就能得到对应的期待值。而劝导一个人去吃饭会有一定的花费,比如杰是一个富 有 原 则 性的人,除非你给他5元或5元以上的钱,否则他是绝对不会一起去的。现在队长有S元钱,告诉你队长对于每个人的期待值以及劝导他去吃饭的最小花费,队长想知道在花费不超过S元的前提下,他能获得的最大期待值。值得注意的是,队长要劝导一个人去吃饭,必须先劝导他依赖的人去吃饭(如果有的话)。(换言之,u依赖v,要劝导u去吃饭,必须先劝导v)。另外,如果依赖关系构成了一个环(比如1依赖2,2依赖3,3依赖1),队长会感觉自己受到了侮辱,所以不会劝导这个环的任何一个人。
输入描述
第一行两个整数,分别代表集训队的人数,队长的总钱数,以及集训队的依赖关系数。第二行n个整数,其中代表第i个人的期待值第三行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
说明:
构成环啦,都不会劝导,所以答案是0C++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; }