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\rightarrow 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;
}