CCPC 2016 杭州 E. Master of Subgraph(点分治+bitset优化DP)

题目链接:http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf

题意:给定一棵有 n 个结点的树和一个数 m,对于 i ∈ [1,m] 问是否存在一个子图结点的权值和为 i 。

题解:一个显然的思路是树上做背包,但显然会 T。要遍历全部子图,考虑进行点分治,然后合并的时候用 bitset 优化背包,时间复杂度O(nmlogn / 64),且时限给了 8s。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define ull unsigned long long
 5 #define mst(a,b) memset((a),(b),sizeof(a))
 6 #define mp(a,b) make_pair(a,b)
 7 #define pi acos(-1)
 8 #define pii pair<int,int>
 9 #define pb push_back
10 const int INF = 0x3f3f3f3f;
11 const double eps = 1e-6;
12 const int maxn = 3e3 + 10;
13 const int maxm = 1e5 + 10;
14 const ll mod =  998244353;
15 
16 int n,m;
17 vector<int>vec[maxn];
18 bool used[maxn];
19 int a[maxn],root,sz[maxn],son[maxn],all;
20 
21 void getroot(int u,int fa) {
22     sz[u] = 1, son[u] = 0;
23     for(int i = 0; i < vec[u].size(); i++) {
24         int v = vec[u][i];
25         if(used[v] || v == fa) continue;
26         getroot(v,u);
27         sz[u] += sz[v];
28         son[u] = max(son[u],sz[v]);
29     }
30     son[u] = max(son[u],all - son[u]);
31     if(son[u] < son[root]) root = u;
32 }
33 
34 bitset<maxm>bit[maxn],ans;
35 
36 void calc(int u,int fa) {
37     sz[u] = 1, bit[u] <<= a[u];
38     for(int i = 0; i < vec[u].size(); i++) {
39         int v = vec[u][i];
40         if(used[v] || v == fa) continue;
41         bit[v] = bit[u];
42         calc(v,u);
43         sz[u] += sz[v];
44         bit[u] |= bit[v];
45     }
46 }
47 
48 void solve(int u) {
49     used[u] = true;
50     bit[u].reset(), bit[u].set(0);
51     calc(u,0);
52     ans |= bit[u];
53     for(int i = 0; i < vec[u].size(); i++) {
54         int v = vec[u][i];
55         if(used[v]) continue;
56         root = 0;
57         all = sz[v];
58         getroot(v,0);
59         solve(root);
60     }
61 }
62 
63 int main() {
64 #ifdef local
65     freopen("data.txt", "r", stdin);
66 //    freopen("data.txt", "w", stdout);
67 #endif
68     int t;
69     scanf("%d",&t);
70     while(t--) {
71         ans.reset();
72         scanf("%d%d",&n,&m);
73         for(int i = 0; i <= n; i++) vec[i].clear(),used[i] = false;
74         for(int i = 1; i < n; i++) {
75             int u,v;
76             scanf("%d%d",&u,&v);
77             vec[u].push_back(v);
78             vec[v].push_back(u);
79         }
80         for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
81         root = 0;
82         son[0] = 1e9;
83         all = n;
84         getroot(1,0);
85         solve(root);
86         for(int i = 1; i <= m; i++) printf("%d",(int)ans[i]);
87         printf("\n");
88     }
89     return 0;
90 }

 

posted on 2018-11-19 14:04  scau_lok  阅读(393)  评论(0编辑  收藏  举报

导航