F - Tree and Constraints 以子集为状态容器的 01背包

这个m <=20 就是暗示可以状压。
然后这里思路是把每条边 能🔥贡献给m个条件中的几个。。
这个数据统计出来。
然后就是跑01背包了。每条边的贡献。。选还是不选。01经典框架了
timu

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define ll __int128_t
#define ar array<int, 2>
#define arr array<int, 3>
int  n, m, k, inf = 1LL << 61, mod = 998244353;// 1e9+7;
const int N = 5e5 + 50;
vector<ar>mp[N];
int c[N];
int dfs(int u, int p, int i, int t) {//这个手法还是挺经典的  根路径 切一半的苹果
	if (u == t)
		return 1;
	for (auto[v, j] : mp[u]) {
		if (v == p)
			continue;
		if (dfs(v, u, i, t)) {
			c[j] |= 1 << i;
			return 1;
		}
	}
	return 0;
};
void solve() {
	cin >> n;
	for (int i = 0; i < n - 1; ++i) {
		int x, y;
		cin >> x >> y;
		mp[x].push_back({y, i});
		mp[y].push_back({x, i});
	}
	cin >> m;
	for (int i = 0; i < m; ++i) {
		int x, y;
		cin >> x >> y;
		dfs(x, -1, i, y);
	}
	
	vector<int>f(1 << m);
	f[0] = 1;
	for (int i = 0; i < n - 1; ++i) {//01背包  每条边可选可不选
		for (int s = (1 << m) - 1; s >= 0; s--)
			f[s | c[i]] += f[s];
	}
	cout << f.back();
};


//这题我知道怎么做。。但是。。挺抽象 说实话。。
// 他是对于m对 上所有的边。。进行一个那条边。。被那个条件需要到。。
//实际上就是一个01背包。。但是。。抽象。







signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout << fixed << setprecision(15);
#ifdef DEBUG
	freopen("../1.in", "r", stdin);
#endif
	//init_f();
	//init();
	//expr();
	// int T; cin >> T; while(T--)
	solve();
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值