BJ simulation tree [tree dp]

Topic description:

give one n A tree of sideband weights of nodes, which is required to be selected on the tree k points a 1 , a 2 , . . . , a k , so that i = 1 k 1 d i s ( a i , a i + 1 ) minimum. 1 k n 3000

Problem solving ideas:

First of all, the answer must be a connected subtree, and it is 2*subtree edge weight-subtree diameter length.

This is a better dp.

g [ x ] [ i ] means with x is selected in the subtree of the root i points and including x (the same is true below) twice the sum of the smallest edge weights, f 0 [ x ] [ i ] Indicates that the diameter of one end is x f 1 [ x ] [ i ] Express x It is not the optimal value at one end of the diameter. It can be transferred according to the definition. The dp property can ensure that the selected diameter is indeed the true diameter.

The time complexity is O ( n 2 )

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int getint()
{
    int i=0,f=1;char c;
    for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
    if(c=='-')c=getchar(),f=-1;
    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
    return i*f;
}
const int N=3005,INF=0x3f3f3f3f;
int n,k,ans=INF,size[N],g[N][N],f0[N][N],f1[N][N];
int tot,first[N],nxt[N<<1],to[N<<1],w[N<<1];
void add(int x,int y,int z)
{
    nxt[++tot]=first[x],first[x]=tot,to[tot]=y,w[tot]=z;
}
void checkmin(int &x,int y){x=x<=y?x:y;}
void dfs(int u,int fa)
{
    size[u]=1;g[u][1]=f0[u][1]=f1[u][1]=0;
    for(int e=first[u];e;e=nxt[e])
    {
        int v=to[e];if(v==fa)continue;
        dfs(v,u);
        for(int i=size[u];i;i--)
            for(int j=size[v];j;j--)
            {
                checkmin(g[u][i+j],g[u][i]+g[v][j]+w[e]*2);
                checkmin(f0[u][i+j],f0[u][i]+g[v][j]+w[e]*2);
                checkmin(f0[u][i+j],g[u][i]+f0[v][j]+w[e]);
                checkmin(f1[u][i+j],f1[u][i]+g[v][j]+w[e]*2);
                checkmin(f1[u][i+j],g[u][i]+f1[v][j]+w[e]*2);
                checkmin(f1[u][i+j],f0[u][i]+f0[v][j]+w[e]);
            }
        size[u]+=size[v];
    }
}
int main()
{
    //freopen("lx.in","r",stdin);
    memset(g,INF,sizeof(g));
    memset(f0,INF,sizeof(f0));
    memset(f1,INF,sizeof(f1));
    n=getint(),k=getint();
    for(int i=1;i<n;i++)
    {
        int x=getint(),y=getint(),z=getint();
        add(x,y,z),add(y,x,z);
    }
    dfs(1,0);
    for(int i=1;i<=n;i++)if(size[i]>=k)ans=min(ans,min(f0[i][k],f1[i][k]));
    cout<<ans<<'\n';
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326142397&siteId=291194637