2019牛客国庆集训派对day3 J.买一送一(dfs+组合数学)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019牛客国庆集训派对day3 J.买一送一(dfs+组合数学)相关的知识,希望对你有一定的参考价值。

LINK

从根节点 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牛客国庆集训派对day3 时间旅行(思维)

2019牛客国庆集训派对day1 D.Modulo Nine(巧妙的dp)

2019牛客国庆集训派对day1 F.4 Buttons(思维)

2019牛客国庆集训派对day1 H.有向图(高斯消元)

2019牛客国庆集训派对day2 C.Just h-index(主席树)

2019牛客国庆集训派对day2 J.Vertex Cover(思维,组合数学算贡献)