题
芬特船长参与了另一个寻宝行动,但只发现了一个奇怪的问题。这个问题可能与宝藏的位置有关,也可能与此无关。这就是为什么弗林特船长决定把解决这个问题的任务留给他的船员,并给了他们一个高得离谱的奖励:一天假。
有两个数组a和b的长度n。初始ans = 0,定义如下操作:
1.选择位置i(1≤i≤n);
2.在ans中加上a[i];
3.如果b[i]≠- 1,则将a[b[i]]中加上a[i]。
对每个i(1≤i≤n)执行一次操作,可以得到的最大ans值是多少?
Bogdan叔叔渴望得到奖励,所以他请求你帮他找到最优的位置顺序来对它们进行操作。
Input
第一行包含整数n(1≤n≤2?105)——数组的长度a和b。
第二行包含n整数a1,a2,…,an(?106≤ai≤106)。
第三行包含n整数b1,b2,…,bn(1≤bi≤n或bi=?1)。
附加约束:保证对于任意i(1≤i≤n),序列b[i],b[b[i]],b[b[b[i]]],… 都不是循环的,即总是以?1结束。
Output
在第一行中,打印您可以获得的最大ans字体。
在第二行中,打印操作顺序:nn不同的整数p1,p2,…,pn(1≤pi≤n)。pi是在第i步应该选择的位置。如果有多个订单,打印其中任何一个。
Examples
Input
3 1 2 3 2 3 -1
Output
10 1 2 3
Input
2 -1 100 2 -1
Output
99 2 1
Input
10 -10 -1 2 2 5 -2 -3 -4 2 -6 -1 -1 2 2 -1 5 5 7 7 9
Output
-9 3 5 6 1 9 4 10 7 8 2
第一个样例: 1 + (1 + 2) + (3 + 3) = 10
代码
#include "stdio.h"
#include "algorithm"
#include "iostream"
#include "string.h"
#include "vector"
#include "queue"
using namespace std;
int n,m;
long long sum=0;
long long a[200009],b[200009],c[200009];
int main()
{
queue<int>q;
vector<int>good,bad;
cin>>n;
for(int i=1; i<=n; i++)
cin>>a[i];
for(int i=1; i<=n; i++)
{
cin>>b[i];
if(b[i]!=-1)
c[b[i]]++;
}
for(int i=1; i<=n; i++)
{
if(c[i]==0)
q.push(i);
}
while(!q.empty())
{
int u=q.front();
q.pop();
sum+=a[u];
if(a[u]>0)
{
good.push_back(u);
a[b[u]]+=a[u];
c[b[u]]--;
}
else
{
bad.push_back(u);
c[b[u]]--;
}
if(c[b[u]]==0)
q.push(b[u]);
}
cout<<sum<<endl;
for(int i=0; i<good.size(); i++)
cout<<good[i]<<' ';
for(int i=bad.size()-1; i>=0; i--)
cout<<bad[i]<<' ';
}
|