E - Red and Blue Tree(计数&背包)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了E - Red and Blue Tree(计数&背包)相关的知识,希望对你有一定的参考价值。

E - Red and Blue Tree(计数&背包)

一共 n − 1 n-1 n1条边,预处理路径中每条边经过的次数 c i c_i ci

则令, ∑ i = 0 n − 1 c i = R + B = S \\sum\\limits_{i=0}^{n-1} c_i =R+B=S i=0n1ci=R+B=S

R − B = K R-B=K RB=K

R = S + K 2 R=\\dfrac{S+K}{2} R=2S+K

显然 ( S + K ) ≥ 0 , 且 ( S + K ) (S+K)\\ge 0 ,且(S+K) (S+K)0,(S+K)为偶数。

然后就是选择一部分边涂 R R R使得和为: S + K 2 \\dfrac{S+K}{2} 2S+K,典型的背包问题。

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
vector<vector<pair<int,int>>>G;
vector<int>C;
int dfs(int v,int pre,int goal){
	if(v==goal)return 1;
	for(auto [vv,i]:G[v])if(vv!=pre){
		if(dfs(vv,v,goal)){
			C[i]++;
			return 1;
		}
	}
	return 0;
}
int main(){
	int N, M, K;
	cin >> N >> M >> K;
	vector<int>A(M);
	
	for(int i=0;i<M;i++){
		cin >> A[i];
		A[i]--;
	}
	G.resize(N);
	for(int i=0;i<N-1;i++){
		int x,y;
		cin >> x >> y;
		x--,y--;
		G[x].push_back({y,i});
		G[y].push_back({x,i});
	}
	
	C.resize(N-1);
	for(int i=0;i<M-1;i++)dfs(A[i],-1,A[i+1]);
	
	int S=0;
	for(int i=0;i<N-1;i++)S+=C[i];
	if((S+K)%2 || S+K<0){
		cout << 0;
		return 0;
	}
	vector<int>dp(100001);
	dp[0]=1;
	for(int i=0;i<N-1;i++)for(int x=100000;x>=C[i];x--)(dp[x]+=dp[x-C[i]])%=mod;
	cout << dp[(S+K)/2];
}

以上是关于E - Red and Blue Tree(计数&背包)的主要内容,如果未能解决你的问题,请参考以下文章

AGC 014E.Blue and Red Tree(思路 启发式合并)

ABC222 E - Red and Blue Tree(思维+dp)

AGC 014 E Blue and Red Tree [树链剖分]

E - Red and Blue Graph(组合数学)

E - Red and Blue Graph(组合数学)

E - Red and Blue Graph(组合数学)