spoj 1825 (树的分治)

  • Post author:
  • Post category:其他


spoj 1825

题目:http://www.spoj.com/problems/FTOUR2/

题目大意:给你一棵节点数为 N 的树,每条树枝有权值,点有黑白两色,问你找一条路径使其进过的黑色的节点数不超过 K 且权值和最大,然后输出这个权值。

思路:继上题的 Tree 之后,漆子超论文的下一道题目,表示看论文、题解和别人代码做了很久。。 = =



用G[ i ][ j ] 表示根节点 的第 i 个儿子经过的黑点数为 j 的最优值,但是 i、j 范围太大了,空间开不下。但是我们不需要保存所有的儿子对应的所有 j ,我们只关心已经算过的节点中每个 j 对应的最大值,所以这里需要优化一下:用f [ i ]  表示已处理的节点中黑点数不超过 i 的最优值,显然,f 具有单调递增性。然后对于当前要处理的节点,算出 g[ i ] ,,然后用g[ i ] 去和 f[ i ]组合更新 ans ,再更新 f[ i ] 就行了,注意:f[ i ]  更新好以后,也要用符合要求的 i 更新 ans ,因为 g[ i ] 有可能不和 f[ i ] 结合,即,根节点为路径的起点或终点。对于每一个根节点,需要对每个儿子按照 dep[ i ] 先进行排序,然后每次只要更新到dep[ i ] 就行了,时间复杂度为排序的复杂度O(NlogN),如果不排序,则最坏情况下,时间复杂度会达到  O(N^2 )。



基本上是照着别人代码来的,先开始一直TLE,然后WA,然后RE,最后才 AC 的。。 = =  WA的原因在于,我把 solve()里的 getted[ root ] =0, 写成 getted[ x ] =0 了。。 T T,而TLE是在于找 root 时,我是按照上一题的方法来的,代码是这样的:

int num[MAXN],maxv[MAXN];

vector <int> node;

void dfs(int u,int fa)
{
    node.push_back(u);
    num[u]=1;
    for(int e = head[u];e!=-1;e= edge[e].next)
    {
        int v = edge[e].t;
        if(getted[v]||v==fa) continue;
        dfs(v,u);
        num[u]+=num[v];
       



版权声明:本文为u010794465原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。