2019牛客国庆集训派对day3 J.买一送一(dfs+组合数学)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019牛客国庆集训派对day3 J.买一送一(dfs+组合数学)相关的知识,希望对你有一定的参考价值。
从根节点 1 1 1开始 d f s dfs dfs
我们保存一个 s u m sum sum表示路径上出现了 s u m sum sum种不同的颜色
当我们 d f s dfs dfs到 u u u点时,显然前面 s u m sum sum种颜色都可以和 p [ u ] p[u] p[u]形成一个合法的对
然而会有重复,也就是我们之前可能已经算过 p [ u ] p[u] p[u]颜色作为对的情况!!
那么就先减去之前的,再加上现在的
然后当 d f s dfs dfs退出点 u u u时,需要把所有数组,变量都还原回去
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e5+10;
vector<int>vec[maxn];
int f[maxn],col[maxn],ans,sum,p[maxn],val[maxn],n;
void dfs(int u,int fa)
{
int temp = val[p[u]] , now = sum;//1到u路径之前最晚出现p[u]的地方
ans -= temp; val[p[u]] = now; ans += now;
f[u] = ans;
if( ++col[p[u]]==1 ) sum++;
for( auto v:vec[u] )
if( v!=fa ) dfs(v,u);
if( --col[p[u]]==0 ) sum--;
ans -= now, val[p[u]] = temp, ans += temp;
}
signed main()
{
while( cin >> n )
{
for(int i=2;i<=n;i++)
{
int x; cin >> x;
vec[x].push_back( i );
}
for(int i=1;i<=n;i++) cin >> p[i];
dfs(1,1);
for(int i=2;i<=n;i++) cout << f[i] << endl;
ans = sum = 0;
for(int i=1;i<=n;i++) vec[i].clear(),f[i] = val[i] = col[i] = 0;
}
}
以上是关于2019牛客国庆集训派对day3 J.买一送一(dfs+组合数学)的主要内容,如果未能解决你的问题,请参考以下文章
2019牛客国庆集训派对day1 D.Modulo Nine(巧妙的dp)
2019牛客国庆集训派对day1 F.4 Buttons(思维)