1. 程式人生 > 實用技巧 >HDU6268 Master of Subgraph(點分治)

HDU6268 Master of Subgraph(點分治)

看上去比較像點分治的裸題,因此也考慮通過根節點的子圖和不通過根節點的子圖。

我們要維護的是,如何做到做完一個兒子後,另一個兒子可以使用前面的資訊,這裡可以使用bitset,題目只給了3000個點其實也提示了這一點

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+10;
const int mod=1e7+7;
int n,idx;
int h[N],ne[N],e[N],w[N];
int cnt[N],vis[N],d[N],sz[N];
int dis[N];
int st[N];
int root; int m; bitset<100010> bit[3030],ans; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs_root(int u,int fa,int tot){ int i; sz[u]=1; int ans=0; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa||vis[j]) continue; dfs_root(j,u,tot); sz[u]
+=sz[j]; ans=max(ans,sz[j]); } ans=max(ans,tot-sz[u]); if(ans*2<=tot){ root=u; } } void dfs_sz(int u,int fa){ sz[u]=1; int i; for(i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa||vis[j]) continue; dfs_sz(j,u); sz[u]
+=sz[j]; } } void get(int u,int fa){ bit[u]<<=w[u]; for(int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa||vis[j]) continue; bit[j]=bit[u]; get(j,u); bit[u]|=bit[j]; } } void work(int u,int tot){ dfs_root(u,-1,tot); u=root; vis[u]=1; dfs_sz(u,-1); bit[u].reset(); bit[u].set(0); get(u,-1); ans|=bit[u]; for(int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(vis[j]) continue; work(j,sz[j]); } } int main(){ //ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; scanf("%d%d",&n,&m); int i; ans.reset(); idx=0; for(i=0;i<=n;i++){ h[i]=-1; vis[i]=0; } for(i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add(a,b); add(b,a); } for(i=1;i<=n;i++) scanf("%d",&w[i]); work(1,n); for(i=1;i<=m;i++){ printf("%d",(int)ans[i]); } printf("\n"); } return 0; }