> 文章列表 > D. Captain Flint and Treasure(拓扑排序 + 贪心)

D. Captain Flint and Treasure(拓扑排序 + 贪心)

D. Captain Flint and Treasure(拓扑排序 + 贪心)

Problem - D - Codeforces

芬特队长参与了另一个寻宝活动,但只发现了一个奇怪的问题。这个问题可能与宝藏的位置有关,也可能不是。这就是为什么弗林特船长决定把解决问题的工作交给他的船员,并提供了一个高得离谱的奖励:休息一天。问题本身听起来是这样的……有两个长度为n的数组a和b。最初,ans等于0,并定义如下操作:1. 选择位置i (1 <i<n);2. 在ans的基础上加上a;3.如果b, -1,那么加a;, abi对每一个i (1 Si S n)只执行一次,你能得到的最大ans是多少?Bogdan叔叔急于得到奖励,所以他请求你帮助他找到对他们进行手术的最佳位置顺序。输入第一行包含整数n (1 < n < 2-105) -数组a和b的长度。第二行包含n个整数a1, a2,…, an(-10°< a;< 106)。第三行包含n个整数b1 b2,。,bn (1 < bi < n or b;= 1)。附加约束:它保证对于任意i (1 < i< n)序列b, bbi>bb;?不是循环的,换句话说,它总是以-1结尾。输出在第一行中,打印您可以得到的最大ans。在第二行,打印操作顺序:n个不同的整数P1,P2,Pn (1 pi S n)。p是第i步应该选择的位置。如果有多个订单,打印其中任何一个。

Examples

input

Copy

3
1 2 3
2 3 -1

output

Copy

10
1 2 3 

input

Copy

2
-1 100
2 -1

output

Copy

99
2 1 

input

Copy

10
-10 -1 2 2 5 -2 -3 -4 2 -6
-1 -1 2 2 -1 5 5 7 7 9

output

Copy

-9
3 5 6 1 9 4 10 7 8 2

题解:

如果bi != -1,那么如果进行第i操作,abi += ai,bi可以看作一条i -> bi的边,

又说保证是不循环的,所以构建出来的图大概是这样

由于 abi += ai,是累加操作,ai的值会多次加上,所以,从叶子节点开始操作是最优的,

所以我们进行拓扑排序,每次把入度为0的点存入,并且如果ai >= 0让他的下一个节点+ai

对于叶子节点ai < 0的时候,累计会导致多次加上一个负数,肯定是不行的,所以我们

遍历到入度为0,的点并且ai<0,把它存到栈中

拓扑排序完拿的话,就变成了,先拿-3,然后-2,-1明显这是最优情况 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define int long long
vector<int> p[200050];
int a[200050];
int n;
int du[200050];
void solve()
{cin >> n;for(int i = 1;i <= n;i++){cin >> a[i];}for(int i = 1;i <= n;i++){int x;cin >> x;if(x != -1){du[x] ++;p[i].push_back(x);}}stack<int> s;queue<int> q;for(int i = 1;i <= n;i++){if(du[i] == 0)q.push(i);} vector<int> ans;int res = 0;while(q.size()){int t = q.front();q.pop();if(a[t] >= 0){ans.push_back(t);res += a[t];}elses.push(t);for(auto ne:p[t]){if(a[t] >= 0){a[ne] += a[t];}du[ne]--;if(du[ne] == 0){q.push(ne);}}}while(s.size()){int t = s.top();s.pop();res += a[t];ans.push_back(t);}cout << res <<"\\n";for(auto i:ans){cout <<i<<" ";}
}signed main()
{
//	ios::sync_with_stdio(0);
//	cin.tie(0);cout.tie(0);int t = 1;
//	cin >> t;while(t--){solve(); }
}

源码800