NC22598 Rinne Loves Edges

题意

一棵根为(S)的树,选择性切掉一些边,求使得所有的叶子都不能到达根的最小代价。

思路

树形(DP)

树型(DP)本质上可以说是个搜索——遍历这棵树,在返回的时候维护相关的值。

不管是写(DP)还是写搜索其实都是要分析原问题和子问题分别是什么的,我们的原问题是以(S)为根的子树删掉权值和尽量小的一些边使得(S)和一个叶子节点都不连通,那么子问题也很简单,就是求以(x)为根的子树删掉一些边使得(S)(x)的子树上每个叶子节点都不连通。

状态表示:

(f(u)):使得以(u)为根的子树内的叶子到不了(u)的最小代价。

状态转移:

要想在考虑(u)这个点的子树的时候就实现子树上每个叶子都和(u)不连通,那么有两种情况:把(u)和他的儿子断开,或者是,在(u)的子树上去把所有叶子节点都断开。

[f(u)=sum_{Son(x)}min(f(x),w[u ightarrow x]) ]

边界:

所有的叶子节点(f)值应为一个极大值。

const int N=1e5+10;
vector<PII> g[N];
LL f[N];
int n,m,s;

void dfs(int u,int fa)
{
    bool leaf=true;
    for(int i=0;i<g[u].size();i++)
    {
        int j=g[u][i].fi,w=g[u][i].se;
        if(j == fa) continue;
        leaf=false;
        dfs(j,u);
        f[u]+=min(f[j],(LL)w);
    }

    if(leaf) f[u]=LNF;
}

int main()
{
    cin>>n>>m>>s;

    while(m--)
    {
        int a,b,c;
        cin>>a>>b>>c;
        g[a].pb({b,c});
        g[b].pb({a,c});
    }

    dfs(s,-1);

    cout<<f[s]<<endl;
    //system("pause");
    return 0;
}

原文地址:https://www.cnblogs.com/fxh0707/p/14656322.html