这个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;
}