题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909
点分治的话,每次要做一次树形DP;但时间应该是 siz*m2 的。可以用 FWT 变成 siz*mlogm ,但这里写的是把树变成序列来 DP 的方法,应该是 nlogn*m 的。
树上的一个点,如果选,就可以选它的孩子,所以它向它的第一个孩子连边;如果不选,就会跳到它的下一个兄弟或者是父亲的下一个兄弟之类的,向那边连一条边。
做出树的 dfs 序,把边都连在 dfs 序上;其实那个第一条边一定连向自己 dfs 序+1,即使自己没有孩子也是符合的,所以可以不用连了;第二条边可以通过传父亲的连边对象来解决。
#include
#include
#include
using namespace std;
const int N=1005,M=1025,mod=1e9+7;
int T,n,m,w[N],hd[N],xnt,to[N<<1],nxt[N<<1],siz[N],rt,mn;
int dfn[N],tot,sta[N],top,f[N][M],g[N],nt[N],ans[M]; bool vis[N];
int rdn()
{int ret&#61;0;bool fx&#61;1;char ch&#61;getchar();while(ch>&#39;9&#39;||ch<&#39;0&#39;){if(ch&#61;&#61;&#39;-&#39;)fx&#61;0;ch&#61;getchar();}while(ch>&#61;&#39;0&#39;&&ch<&#61;&#39;9&#39;)ret&#61;ret*10&#43;ch-&#39;0&#39;,ch&#61;getchar();return fx?ret:-ret;
}
int Mx(int a,int b){return a>b?a:b;}
int Mn(int a,int b){return aa:b;}
void upd(int &x){x>&#61;mod?x-&#61;mod:0;}
void init()
{xnt&#61;0;memset(hd,0,sizeof hd);memset(ans,0,sizeof ans); memset(vis,0,sizeof vis);
}
void add(int x,int y){to[&#43;&#43;xnt]&#61;y;nxt[xnt]&#61;hd[x];hd[x]&#61;xnt;}
void getrt(int cr,int fa,int s)
{siz[cr]&#61;1; int mx&#61;0;for(int i&#61;hd[cr],v;i;i&#61;nxt[i])if(!vis[v&#61;to[i]]&&v!&#61;fa){getrt(v,cr,s);siz[cr]&#43;&#61;siz[v];mx&#61;Mx(mx,siz[v]);}mx&#61;Mx(mx,s-siz[cr]);if(mx
}
void dfs(int cr,int fa)
{dfn[cr]&#61;&#43;&#43;tot;g[tot]&#61;w[cr];for(int i&#61;hd[cr],v;i;i&#61;nxt[i])if(!vis[v&#61;to[i]]&&v!&#61;fa)dfs(v,cr);
}
void dfsx(int cr,int fa,int lst)
{nt[dfn[cr]]&#61;lst;int l&#61;top&#43;1;for(int i&#61;hd[cr],v;i;i&#61;nxt[i])if(!vis[v&#61;to[i]]&&v!&#61;fa)sta[&#43;&#43;top]&#61;v;int r&#61;top;for(int i&#61;hd[cr],v,p0&#61;l;i;i&#61;nxt[i])if(!vis[v&#61;to[i]]&&v!&#61;fa){dfsx(v,cr,p0&#61;&#61;r?lst:dfn[sta[p0&#43;1]]);p0&#43;&#43;;}
}
void solve(int cr,int s)
{vis[cr]&#61;1;tot&#61;0;dfs(cr,0);top&#61;0;dfsx(cr,0,s&#43;1);for(int i&#61;1;i<&#61;s&#43;1;i&#43;&#43;)memset(f[i],0,sizeof f[i]);f[1][0]&#61;1;for(int i&#61;1;i<&#61;s;i&#43;&#43;)for(int j&#61;0;j
}
int main()
{T&#61;rdn();while(T--){n&#61;rdn();m&#61;rdn();for(int i&#61;1;i<&#61;n;i&#43;&#43;)w[i]&#61;rdn();init();for(int i&#61;1,u,v;i
}