Rinne Loves Edges
Rinne Loves Edges
http://www.nowcoder.com/questionTerminal/080d6bd6edb043bd855f633f70edde1d
树形DP
首先,中文题,就不再阐述题意了。
然后,具体怎么dp呢?首先不考虑树上,如果是一条序列上的话,肯定就是这条序列上的最小值了,现在其实实则变成了多条序列。
我们动态规划的主要思想就是在于,是割下面的点的代价要小,还是割目前的边要更好些,所以用dp[u]记录,u结点为子树的根结点的时候,断开它到它的叶子结点的最小代价是多少。
然后动态规划的过程就简单了:
#include <iostream> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <limits> #include <vector> #include <stack> #include <queue> #include <set> #include <map> #include <bitset> //#include <unordered_map> //#include <unordered_set> #define lowbit(x) ( x&(-x) ) #define pi 3.141592653589793 #define e 2.718281828459045 #define INF 0x3f3f3f3f3f3f3f3f #define eps 1e-8 #define HalF (l + r)>>1 #define lsn rt<<1 #define rsn rt<<1|1 #define Lson lsn, l, mid #define Rson rsn, mid+1, r #define QL Lson, ql, qr #define QR Rson, ql, qr #define myself rt, l, r #define MP(a, b) make_pair(a, b) using namespace std; typedef unsigned long long ull; typedef unsigned int uit; typedef long long ll; const int maxN = 1e5 + 7; int N, M, root, head[maxN], cnt; struct Eddge { int nex, to; ll val; Eddge(int a=-1, int b=0, ll c=0):nex(a), to(b), val(c) {} }edge[maxN << 1]; inline void addEddge(int u, int v, ll w) { edge[cnt] = Eddge(head[u], v, w); head[u] = cnt++; } inline void _add(int u, int v, ll w) { addEddge(u, v, w); addEddge(v, u, w); } ll dp[maxN]; void dfs(int u, int fa) { ll sum = 0; bool ok = false; for(int i=head[u], v; ~i; i=edge[i].nex) { v = edge[i].to; if(v == fa) continue; ok = true; dfs(v, u); sum += min(dp[v], edge[i].val); } dp[u] = sum; if(!ok) dp[u] = INF; } inline void init() { cnt = 0; for(int i=1; i<=N; i++) head[i] = -1; } int main() { scanf("%d%d%d", &N, &M, &root); init(); ll w; for(int i=1, u, v; i <= M; i++) { scanf("%d%d%lld", &u, &v, &w); _add(u, v, w); } dfs(root, 0); printf("%lld\n", dp[root]); return 0; }