Rinne Loves Edges【树形dp】

题目描述

Rinne 最近了解了如何快速维护可支持插入边删除边的图,并且高效的回答一下奇妙的询问。

她现在拿到了一个 n 个节点 m 条边的无向连通图,每条边有一个边权 wiw_iwi​

现在她想玩一个游戏:选取一个 “重要点” S,然后选择性删除一些边,使得原图中所有除 S 之外度为 1 的点都不能到达 S。

定义删除一条边的代价为这条边的边权,现在 Rinne 想知道完成这个游戏的最小的代价,这样她就能轻松到达 rk1 了!作为回报,她会让你的排名上升一定的数量。

输入描述:

第一行三个整数 N,M,S,意义如「题目描述」所述。

接下来 M 行,每行三个整数 u,v,w 代表点 u 到点 v 之间有一条长度为 w 的无向边。

输出描述:

一个整数表示答案。

示例1

输入

4 3 1 
1 2 1 
1 3 1 
1 4 1

输出

3

说明

需要使得点 2,3,4 不能到达点 1,显然只能删除所有的边,答案为 3

示例2

输入

4 3 1 
1 2 3 
2 3 1 
3 4 2

输出

1

说明

需要使得点 4 不能到达点 1,显然删除边 2↔3是最优的。

备注:

2≤S≤N≤10^5,M=N−1保证答案在 C++ long long 范围内。

题解:很明显就可以得到转移公式dp[x]+=min(dp[v],w);

AC代码:

#include <bits/stdc++.h>
using namespace std;
#define sc(x) scanf("%d",&x)
#define pb push_back
#define ll long long
using namespace std;
const int Max=1e6+5,mod=1e9+7;
const ll INF=1e18;
struct node{
	int to;
	ll data;
};
vector<node>mp[Max];
ll dp[Max];
void dfs(int fa,int x){
	for(int i=0;i<mp[x].size();i++){
		int v=mp[x][i].to;
		if(fa==v) continue;
		dfs(x,v);
		dp[x]+=min(dp[v],mp[x][i].data);
	}
}
int main(){
	int n;sc(n);int m;sc(m);int s;sc(s);
	for(int i=0;i<n-1;i++){
		int u,v,w;
		sc(u);sc(v);sc(w);
		mp[u].pb((node){v,w});
		mp[v].pb((node){u,w});
	}
	for(int i=1;i<=n;i++){
		if(mp[i].size()==1) dp[i]=INF;
		else dp[i]=0;
	}
	dp[s]=0;
	dfs(-1,s);
	printf("%lld\n",dp[s]);
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瘾ิۣۖิۣۖิۣۖิꦿ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值