HDU-4313-matrix-tree DP or greedy

Source: Internet
Author: User

Give n vertices and n-1 edges (a spanning tree ). Given K points, there is a robot on these points. Finally, let you delete some edges so that any two robots cannot reach each other, and the sum of the deleted edges must be minimized. Http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4313

Solution:

First, we can see two options without decision-making.

1. If the root node is a dangerous point, the Child tree cannot have a dangerous point.

DP [u] [0]: The smallest edge weight that needs to be deleted when there is no dangerous knot in the child node connected to u. If U is a dangerous node, the value is infinite.

DP [u] [1]: The smallest edge weight to be deleted when there is a dangerous knot in the child node connected to u.

Consider the subtree with u as the root node as a leaf node.

If I is a leaf node: If I is a dangerous point DP [I] [0] = inf, DP [I] [1] = 0; otherwise, DP [I] [0] = DP [I] [1] = 0;
If I is not a leaf node: If I is a dangerous point DP [I] [0] = inf, DP [I] [1] = Sigma min (DP [son] [0], DP [son] [1] + W );
Otherwise, DP [I] [0] = Sigma min (DP [son] [0], DP [son] [1] + W ), DP [I] [1] = min (DP [I] [0]-min (DP [son] [0], DP [son] [1] + W) + dp [son] [1]).

I said that I am very orz, but I can't do it. I haven't understood it for a day. I felt that I couldn't get stuck with this question, so I got stuck with the code.

#include <cstdio>#include <cstring>const int MAXN = 100005;const __int64 INF = 10000000000000000LL;__int64 dp[MAXN][2];int n, k;struct Edge{    int v, w, next;}edge[MAXN * 2];int edgeNumber, head[MAXN];bool haveMachine[MAXN];inline void addEdge(int u, int v, int w){    edge[edgeNumber].v = v;    edge[edgeNumber].w = w;    edge[edgeNumber].next = head[u];    head[u] = edgeNumber ++;}inline __int64 min(const __int64 &x, const __int64 &y){    return x < y ? x : y;}void dfs(int u, int father){    if(haveMachine[u])    {        dp[u][0] = INF;        dp[u][1] = 0;    }    else    {        dp[u][0] = 0;        dp[u][1] = INF;    }    __int64 minS = INF;    __int64 count = 0;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v = edge[i].v;        int w = edge[i].w;        if(v != father)        {            dfs(v, u);            if(haveMachine[u])            {                dp[u][1] += min(dp[v][0], dp[v][1] + w);            }            else            {                dp[u][0] += min(dp[v][0], dp[v][1] + w);                ++ count;                if(dp[v][0] <= dp[v][1] + w)                {                    if(minS > dp[v][1] - dp[v][0])                    {                        minS = dp[v][1] - dp[v][0];                    }                }                else                {                    if(minS > - w)                    {                        minS = - w;                    }                }            }        }    }    if(!haveMachine[u] && count)    {        dp[u][1] = dp[u][0] + minS;    }}int main(){    int t;    int x, y, z;    scanf("%d", &t);    while(t--)    {        scanf("%d%d", &n, &k);        edgeNumber = 0;        memset(head, -1, sizeof(head));        for(int i=1;i<n;++i)        {            scanf("%d%d%d",&x,&y,&z);            addEdge(x, y, z);            addEdge(y, x, z);        }        memset(haveMachine, false, sizeof(haveMachine));        for(int i=0;i<k;++i)        {            scanf("%d", &x);            haveMachine[x] = true;        }        dfs(0, -1);        if(haveMachine[0])        {            printf("%I64d\n", dp[0][1]);        }        else        {            printf("%I64d\n", min(dp[0][0], dp[0][1]));        }    }    return 0;}  

As a result, I finally got a little understanding. This is another code that I can understand. There are comments in it, and you will be very open when you read the comments.

Here, I would like to thank the city again. The purpose of tree DP is to only consider the son of U and U when recursion to U. In this way, I understand.

Assume U has five children, two risks. For the outside, what kind of sub-tree is safe? Remove all dangerous edges.

How can this problem be considered unsafe? Only one side is broken. (Note: For the inside of the subtree of U, it must be safe, because when u is a leaf, whether it is dangerous or not, it must be harmless to itself ).

Then you can easily figure it out.

# Include <iostream> # include <cstdio> # include <vector> # include <cstring> using namespace STD; const _ int64 INF = 1e13; const int n = 111111; __int64 DP [N] [2]; // DP [I] [0] indicates that this subtree does not need to be disconnected from the top. // DP [I] [1] indicates that it needs to be disconnected from the top Int Is [N]; vector <pair <int, int> V [N]; inline _ int64 min (_ int64 A, _ int64 B) {return a <B? A: B;} void DFS (INT U, int pre) {int Len = V [u]. size (); If (is [u]) {DP [u] [0] = inf; // This is not possible =-DP [u] [1] = 0 ;} else {DP [u] [0] = 0; DP [u] [1] = 0;} For (INT I = 0; I <Len; I ++) {int VV = V [u] [I]. first; If (VV = pre) continue; DFS (VV, u) ;__ int64 W = V [u] [I]. second; // It is so short, but you don't understand it... // DP [I] [0] indicates that this subtree does not need to be broken from the top, therefore, this subtree is safe. // DP [I] [1] indicates that it needs to be broken from the above _ int64 T1 = DP [VV] [1]; _ int64 T0 = min (t1 + W, DP [VV] [0]); // you need the minimum value of this edge or not, this is safe. If (is [u]) {DP [u] [1] + = T0; // how can it all be broken from the above? Just take the minimum value, however, the sub-tree of u should be safe. // It is impossible not to break with the above.} Else {// until this edge is related to the previous edge. // To be dangerous, or the previous U is safe, the subtree is insecure now, // or the previous U is insecure, and the subtree is safe now. DP [u] [1] = min (DP [u] [0] + T1, DP [u] [1] + T0); // to ensure security, consistency is always safe. DP [u] [0] + = T0 ;}} int main () {int t, n, k; scanf ("% d", & T ); while (t --) {scanf ("% d", & N, & K); For (INT I = 0; I <n; I ++) V [I]. clear (); For (INT I = 1; I <n; I ++) {int A, B, C; scanf ("% d ", & A, & B, & C); V [A]. push_back (make_pair (B, c); V [B]. push_back (make_pair (a, c);} memset (is, 0, sizeof (is); For (INT I = 0; I <K; I ++) {int A; scanf ("% d", & A); is [a] = 1;} DFS (0,-1 ); __int64 ans = DP [0] [0]; If (DP [0] [1] <ans) ans = DP [0] [1]; cout <ans <Endl;} return 0 ;}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.