Rinne Loves Edges(树形dp)

题目链接:https://ac.nowcoder.com/acm/contest/370/F

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld

题目描述 

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

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

现在她想玩一个游戏:选取一个 “重要点” 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↔32↔3是最优的。

备注:

2≤S≤N≤105,M=N−12≤S≤N≤105,M=N−1,保证答案在 C++ long long 范围内。
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring> 
using namespace std;
typedef long long ll;
const int N=1e5+5;
struct node{
	int v;
	ll w;
	node(){}
	node(int vv,ll ww){
		v=vv;
		w=ww;
	}
};
bool vis[N];
ll dp[N];
vector<node>v[N];
const ll INF=1e16;
ll dfs(int u){
	ll ans=0;
	for(int i=0;i<v[u].size();i++){
		int t=v[u][i].v;
		ll w=v[u][i].w;
		if(vis[t]) continue;
		vis[t]=true;		
		ans+=min(dfs(t),w);		
	}	
	return dp[u]=ans?ans:INF;
}
int main(){
	int n,m,s;
	scanf("%d%d%d",&n,&m,&s);
	for(int i=1;i<=m;i++){
		int a,b;
		ll w;
		scanf("%d%d%lld",&a,&b,&w);
		v[a].push_back(node(b,w));
		v[b].push_back(node(a,w));
	}
    vis[s]=true;
	dfs(s);
	printf("%lld\n",dp[s]);
	return 0;
}
 

猜你喜欢

转载自blog.csdn.net/qq_42936517/article/details/88093356