题意
一棵根为(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;
}