传送门 https://www.luogu.org/problemnew/show/P1352
题意: 上司和直接下属, 不能同时去一个聚会, 问可邀请到的人的快乐值最大是多少;
参考 https://www.luogu.org/blog/mak2333/solution-p1352 :https://www.luogu.org/blog/mak2333/solution-p1352
思路:
首先我们们分析一下这道题, 对于每一个人, 它所做的决定对上司和下属都有影响, 我们可以只看一方, 也就是上司对下属的影响, 因为这样的影响是相互的.
状态如果为 f[i] 表示第 i 个人的位置能获得最大的幸福行吗?
由于我们的选择具有后效性, 因为你去或不去对下属有影响, 那显然不行. 遇到这种情况我们该怎么办?
加一维
由于后效性实质上是我们对于状态的性质不够清楚, 所以我们再加一维以实现就算你加还是不加我们都可以记录下来. 所以状态其实是很好想的. 想出状态后, 容易推出方程为
- dp[i][0]+=sum(max(dp[son][1],dp[son][0])); // 显然, 你不去, 那下属就可以想去就去.
- dp[i][1]=sum(dp[son][0])+happy[i]; // 显然你去了那下属就一定不能去.
由此我们就可以愉快的 DFS 了.
- #include <iostream>
- #include <cstdio>
- #include <algorithm>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <map>
- #include <set>
- #include <queue>
- #include <list>
- #include <iterator>
- #include <cmath>
- using namespace std;
- #define lson (l , mid , rt <<1)
- #define rson (mid + 1 , r , rt << 1 | 1)
- #define debug(x) cerr << #x << "=" << x << "\n";
- #define pb push_back
- #define pq priority_queue
- #define Pll pair<ll,ll>
- #define Pii pair<int,int>
- #define fi first
- #define se second
- #define OKC ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
- #define FT(A,B,C) for(int A=B;A <= C;++A) // 用来压行
- typedef long long ll;
- typedef unsigned long long ull;
- /*-----------------show time----------------*/
- const int maxn = 6009;
- vector<int>mp[maxn];
- int n;
- int hp[maxn],dp[maxn][2],fa[maxn];
- void dfs(int u,int o)
- {
- for(int i=0; i<mp[u].size(); i++)
- {
- int tmp = mp[u][i];
- if(tmp==o)continue;
- dfs(tmp,u);
- dp[u][1] = max(dp[tmp][0]+dp[u][1],dp[u][1]);
- dp[u][0] += max(dp[tmp][1],dp[tmp][0]);
- }
- dp[u][1] += hp[u];
- }
- int main(){
- scanf("%d", &n);
- for(int i = 1; i<=n; i++)scanf("%d" , hp+i),fa[i] = i;
- for(int i =1; i<=n; i++)
- {
- int u,v;
- scanf("%d%d", &u, & v);
- if(u+v==0)break;
- mp[v].pb(u);
- fa[u] = v;
- }
- int s = n;
- while(s!=fa[s])
- {
- s = fa[s];
- }
- dfs(s,-1);
- printf("%d\n",max(dp[s][1],dp[s][0]));
- return 0;
- }
- DFS
参考中还提到, 如果人数过多, 或者是一条链的时候, 可以用 BFS + 队列, 拓扑排序优化. 我感觉主要思路, 就是把从子节点到父节点的路径找出来
来源: http://www.bubuko.com/infodetail-2648402.html