【SPOJ1825】Free Tour II-点分治+桶排序
2018-04-02 22:28
344 查看
测试地址:Free Tour II
题目大意:给定一棵树,边有边权,点分为黑点和白点,求经过不超过KK个黑点的路径的最大边权和。
做法:本题需要用到点分治+桶排序。
首先看到求这样的路径问题,如果DP看上去非常难做,就考虑用点分治。
对于点分治中每个块的根节点,我们考虑求经过这个根节点的合法路径的最大边权和。对于块中的每个点我们得到了一个数对(x,y)(x,y),其中xx为从根到该点路径上经过的黑点数(为了方便,这里不包括根节点),yy为路径和。那么我们维护一个数组hh,其中h(i)h(i)为经过不超过ii个点的路径的最大边权和,并且路径一端在根节点,另一端在已经处理过的点中。然后对于正在处理的块中的每一个点,我们实际上就是要求,在x1+x2+black(root)≤kx1+x2+black(root)≤k的条件下,h(x1)+y2h(x1)+y2的最大值,这个我们就可以用两个指针求出了。
然而注意到,上述算法的复杂度最快也是O(nlog2n)O(nlog2n)的,再看看数据范围和这个OJ的名字……没办法,优化吧。
优化的方法是,我们把要处理的块按照大小从小到大排序,显然经过的黑点数量不超过max(size)max(size),那么我们把各种排序用桶排序解决,那么每一块的时间复杂度就是O(max(size))O(max(size))的,又因为我们已经将块按照大小从小到大排序,所以这个步骤的总时间复杂度就是O(∑size)O(∑size),这样我们就把算法的时间复杂度降为O(nlogn)O(nlogn)了,可以通过此题。
以下是本人代码:
题目大意:给定一棵树,边有边权,点分为黑点和白点,求经过不超过KK个黑点的路径的最大边权和。
做法:本题需要用到点分治+桶排序。
首先看到求这样的路径问题,如果DP看上去非常难做,就考虑用点分治。
对于点分治中每个块的根节点,我们考虑求经过这个根节点的合法路径的最大边权和。对于块中的每个点我们得到了一个数对(x,y)(x,y),其中xx为从根到该点路径上经过的黑点数(为了方便,这里不包括根节点),yy为路径和。那么我们维护一个数组hh,其中h(i)h(i)为经过不超过ii个点的路径的最大边权和,并且路径一端在根节点,另一端在已经处理过的点中。然后对于正在处理的块中的每一个点,我们实际上就是要求,在x1+x2+black(root)≤kx1+x2+black(root)≤k的条件下,h(x1)+y2h(x1)+y2的最大值,这个我们就可以用两个指针求出了。
然而注意到,上述算法的复杂度最快也是O(nlog2n)O(nlog2n)的,再看看数据范围和这个OJ的名字……没办法,优化吧。
优化的方法是,我们把要处理的块按照大小从小到大排序,显然经过的黑点数量不超过max(size)max(size),那么我们把各种排序用桶排序解决,那么每一块的时间复杂度就是O(max(size))O(max(size))的,又因为我们已经将块按照大小从小到大排序,所以这个步骤的总时间复杂度就是O(∑size)O(∑size),这样我们就把算法的时间复杂度降为O(nlogn)O(nlogn)了,可以通过此题。
以下是本人代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n,k,m,tot=0,first[200010]={0}; int siz[200010],mxson[200010],q[200010],top; int srt[200010]={0},nex[200010]={0},black[200010]={0}; ll ww[200010]={0},nowblock[200010]={0},past[200010]={0},ans=0; bool vis[200010]={0}; struct edge { int v,next; ll w; }e[400010]; void insert(int a,int b,ll w) { e[++tot].v=b; e[tot].w=w; e[tot].next=first[a]; first[a]=tot; } void dp(int v,int f) { q[++top]=v; siz[v]=1,mxson[v]=0; for(int i=first[v];i;i=e[i].next) if (e[i].v!=f&&!vis[e[i].v]) { dp(e[i].v,v); mxson[v]=max(mxson[v],siz[e[i].v]); siz[v]+=siz[e[i].v]; } } int find(int v) { int ans=1000000000,ansp=0; top=0; dp(v,0); for(int i=1;i<=top;i++) { if (max(siz[v]-siz[q[i]],mxson[q[i]])<ans) ans=max(siz[v]-siz[q[i]],mxson[q[i]]),ansp=q[i]; } return ansp; } void getdown(int v,int f,int passed,ll x) { nowblock[passed]=max(nowblock[passed],x); for(int i=first[v];i;i=e[i].next) if (e[i].v!=f&&!vis[e[i].v]) getdown(e[i].v,v,passed+black[e[i].v],x+e[i].w); } int solve(int v) { v=find(v); vis[v]=1; int blocksiz=1,pastmxsiz=0; for(int i=first[v];i;i=e[i].next) if (!vis[e[i].v]) { siz[e[i].v]=solve(e[i].v); ww[e[i].v]=e[i].w; } for(int i=first[v];i;i=e[i].next) if (!vis[e[i].v]) { nex[e[i].v]=srt[siz[e[i].v]]; srt[siz[e[i].v]]=e[i].v; blocksiz+=siz[e[i].v]; } for(int i=0;i<=blocksiz;i++) while (srt[i]) { getdown(srt[i],0,black[srt[i]],ww[srt[i]]); for(int j=0;j<=i;j++) { if (j>0) nowblock[j]=max(nowblock[j-1],nowblock[j]); if (k-j-black[v]>pastmxsiz) ans=max(ans,nowblock[j]+past[pastmxsiz]); else if (k-j-black[v]>=0) ans=max(ans,nowblock[j]+past[k-j-black[v]]); } for(int j=0;j<=i;j++) { past[j]=max(past[j],nowblock[j]); if (j>0) past[j]=max(past[j],past[j-1]); nowblock[j]=0; } pastmxsiz=i; srt[i]=nex[srt[i]]; } for(int i=0;i<=blocksiz;i++) srt[i]=past[i]=0; vis[v]=0; return blocksiz; } int main() { scanf("%d%d%d",&n,&k,&m); for(int i=1;i<=m;i++) { int x; scanf("%d",&x); black[x]=1; } for(int i=1;i<n;i++) { int a,b;ll w; scanf("%d%d%lld",&a,&b,&w); insert(a,b,w),insert(b,a,w); } solve(1); printf("%lld",ans); return 0; }
相关文章推荐
- SPOJ 1825 Free tour II(树的点分治)
- SPOJ 1825 Free tour II 树分治
- 树分治点分治(spoj1825 Free tour II)
- spoj 1825 Free tour II(树的点分治)
- SPOJ 1825 Free tour II 解题报告(树分治)
- spoj 1825 Free tour II 点分治
- spoj1825 Free tour II 点分治
- Spoj - 1825 Free tour II(树的点分治)
- spoj 1825 Free tour II(树分治+启发式合并)
- 【SPOJ】1825 Free tour II 点分治
- SPOJ 1825 Free tour II 树分治
- SPOJ 1825 FTOUR2 - Free tour II (树上点分治)
- spoj1825 Free tour II(点分治)
- 【SPOJ1825】Free tour II (点分治,启发式)
- SPOJ:Free tour II (树分治+启发式合并)
- SPOJ Free tour II 点分治
- SPOJ 1825 Free tour II
- SPOJ 1825 Free tour II
- SPOJ1825 FTOUR2 - Free tour II
- SPOJ1825:Free tour II