WannaFly挑战赛 28 C msc的宠物(二分答案 + 树形dp)

版权声明:本文为博主原创文章,转载请著名出处 http://blog.csdn.net/u013534123 https://blog.csdn.net/u013534123/article/details/83928538

题意相当于是把一棵树分为k+1个部分,然后使得这么多个部分的极差最大值最小。

首先考虑直接树形dp,由于是在讨论极差,所以我们要想办法表示极差的状态,但是我们发现仅仅用状态表示极差,并不能够很好的转移,而且极差本身也不好表示。在转移的时候,满足一个子树的极差最小值,在考虑别的节点的时候可能并不是最小值,也就是说子问题是有后效性的,这也就意味这直接用dp是做不了的。

所以我们考虑二分答案,转换一下求的东西。我们二分最大的极差,然后考虑在当前极差的情况下最少能够分成多少个部分,或者说最少需要剪断几条边。我们令dp[x][i]表示处理完x的子树,且x所在部分的最小值为i,最少需要减去的边数。显然,如果点i的权值大于点x,那么这个状态是非法的标记为INF。然后考虑转移,显然有两种方式,对于x的任意儿子y,要么和x在同一个部分,要么不在同一个部分。所以有转移方程dp[x][i]+=min(dp[y][i],f[y]+1),其中f[y]表示min(dp[y][k])。即如果和x在同一个部分,那么切断的边数就要考虑上y的子树对应情况下切断的边数;如果不在一个部分,那么考虑上y的子树的边数的同时还要加上1表示切断x与y相连的边。

如此转移,最后的f[1]就表示处理完整棵树之后所需要切断的边的最小条数,与给定的k进行比较即可。时间复杂度O(N^2).具体见代码:

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define pi 3.141592653589793
#define mod 998244353
#define LL long long
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define sf(x) scanf("%d",&x)
#define sc(x,y,z) scanf("%d%d%d",&x,&y,&z)

using namespace std;

const int N = 1010;

int dp[N][N],f[N],a[N],mid,n,k;
int g[N<<1],ls[N<<1],nxt[N<<1],e;

inline void addedge(int x,int y)
{
    g[++e]=y; nxt[e]=ls[x]; ls[x]=e;
}

void dfs(int x,int fa)
{
    for(int i=1;i<=n;i++)
        dp[x][i]=(a[x]>=a[i]&&a[x]<=(LL)a[i]+mid)?0:INF;
    for(int i=ls[x];i;i=nxt[i])
    {
        int y=g[i];
        if (y==fa) continue;
        dfs(y,x);
        for(int j=1;j<=n;j++)
            dp[x][j]+=min(dp[y][j],f[y]+1);
    }
    for(int i=1;i<=n;i++)
        f[x]=min(f[x],dp[x][i]);
}

inline bool check()
{
    memset(f,INF,sizeof(f));
    dfs(1,0); return f[1]<=k;
}

int main()
{
    sf(n); sf(k);
    for(int i=1;i<=n;i++) sf(a[i]);
    for(int i=1;i<n;i++)
    {
        int x,y;
        sf(x); sf(y);
        addedge(x,y);
        addedge(y,x);
    }
    LL l=0,r=2e9,ans;
    while(l<=r)
    {
        mid=l+r>>1;
        if (check()) ans=mid,r=mid-1;
                        else l=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}

觉得博主写的好的话,打赏一下吧,互利互惠……

                                 

猜你喜欢

转载自blog.csdn.net/u013534123/article/details/83928538
今日推荐