P2458 [SDOI2006] security guard [tree dp]

Title Description

Fifty-one advent of an underground supermarket in order to facilitate clear and commanding intensive personnel and vehicles, to avoid confusion and congestion inside the supermarket, ready to call the part of the temporary security from other units to maintain traffic order.

All channels are known as a whole underground supermarket a tree shape; some channels could see each other. Each endpoint (vertex of the tree) General Manager requires that all channels must be someone around the clock guards, security arrangements for the costs of different channels at different endpoints.

A security guard once stood one of the endpoints of a channel, then he can see in addition to hold the end he stood, we could see the other end of this channel, it may also be able to see a security hold multiple endpoints (tree node), it is not necessary at the ends of each channel are the security arrangements.

Programming tasks:

Please help supermarket manager planning arrangements, under the premise can guard all channels endpoints, making minimal funds spent.

Input and output formats

Input formats:

The first line n, the number of nodes in the tree.

The second row to n + 1 lines, each line description information for each endpoint channel, as follows: the reference node i (0 <i <= n), the required security requirements placed node k (< = 10,000), the number m of the son of the edge, then the number m, m are the sons of the node numbers r1, r2, ..., rm.

For a n (0 <n <= 1500) nodes of the tree, the node numbers between 1 to n, and reference numerals will not be repeated.

Output formats:

Minimum funding.

As an example of the right input data

Output data Example:

img

Sample input and output

Input Sample # 1:

6
1 30 3 2 3 4
2 16 2 5 6
3 5 0
4 4 0
5 11 0
6 5 0

Output Sample # 1:

25

Explanation

Sample Description: 2,3,4 node security can be disposed three detention some six nodes, the minimum requirements needed: 25

Resolution:

This question is finished, feeling really improved a lot!


See the solution to a problem are written in three states, although I also wrote a three-state solution (easier to understand), but we coach said: four states can be. So they come out of the four states (in fact, can also be turned into essentially three states, no essential difference between the two).

According to the meaning of problems, we have come to any node other than the leaf node \ (the X-\) , there may be four cases:

If \ (x \) cost position is \ (c_x \) , its parent node \ (FA \) .

  1. \ (x \) position is no security, \ (FA \) location have security
  2. \ (x \) position is no security, \ (FA \) position is no security
  3. \ (x \) locations have security, \ (FA \) location have security
  4. \ (x \) locations have security, \ (FA \) position is no security

Set \ (dp [x] [0/1/2/3 ] \) represents to \ (X \) subtree rooted in, so that each endpoint are covered with minimum cost. Wherein each state corresponds to each of the above situation.

Note the difference between the state and the below-mentioned conditions.

One,

First consider \ (1 \) where, for such \ (X \) , it is assumed that an arbitrary node is a child \ (Y \) , then there must be:

\(dp[x][0]=\sum_{y\in tree(x)} min(dp[y][1],dp[y][3])\)

That is, to make the situation \ (1 \) holds, makes it inevitable from the establishment of the state (ie, \ (y \) is the parent node is no security) transferred over.

two,

We first consider \ (3,4 \) case, because they are more like. . .

I reckon this is a state that can be merged, because no matter \ (x \) is \ (fa \) there is no security, it does not matter, does not affect the transfer.

Easy to draw:

\(dp[x][2/3]=\sum_{y\in{tree(x)}} min(dp[y][0],dp[y][2])+c_x\)

That is, to make the case \ (3,4 \) holds, then \ (y \) is \ (fa \) we must have security.

three,

Here it is more difficult to understand, but with the other solution to a problem is the same idea.

We first clear depiction of our state: set \ (dp [x] [0/1/2/3 ] \) indicates to \ (x \) subtree is the root of each endpoint are covered by get the minimum cost.

In the case of \ (2 \) , there are two decisions that

  1. Selecting from a child node \ (Y \) of \ (1 \) states transferred from ( \ (DP [Y] [1] \) ), time \ (Y \) position no security.
  2. Selecting from a child node \ (Y \) of \ (3 \) states transferred from ( \ (DP [Y] [3] \) ), time \ (Y \) Location security.

It is foreseeable that, if for a node \ (x \) , use it as a root node, all its child nodes \ (y \) to obtain the optimal solution when not placed security (ie \ (x \) stage all from \ (dp [y] [1 ] \) transferred from), it is clear that such a situation is not in our portrait of the state of (root \ (x \) is not covered).

So we have to look special judge, once that happens, we will greedily to make the current state established in the sense that we have set.

That is, looking to spend a minimum contribution that \ (dp [the y-] [3] \) , hold it moved to \ (the X-\) .

How to do it? Quite simply, we put the minimum \ (dp [y] [3 ] -dp [y] [1] \) added to the original state can not be established we draw on the line.

To prove it, in fact, think about it, this is actually the difference between the original a transfer \ (dp [y] [1 ] \) becomes \ (dp [y] [3 ] \) changes in the value of time.

We recommend a good taste of this question, to have a good harvest.

Reference Code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define N 2010
#define MOD 2520
#define E 1e-12
#define INF 0x3f3f3f3f
using namespace std;
//start from 1
struct rec{
    int next,ver;
}g[N<<1];
int head[N],tot,n,dp[N][4],a[N];
bool v[N];
inline int read()
{
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
void add(int x,int y)
{
    g[++tot].ver=y;
    g[tot].next=head[x],head[x]=tot;
}
void calc(int x)
{
    v[x]=1;
    int sum=0,minn=INF;
    dp[x][2]=a[x];dp[x][3]=a[x];
    for(int i=head[x];i;i=g[i].next){
        int y=g[i].ver;
        if(v[y]) continue;
        calc(y);
        //0fa有self没有,1fa没有self没有,2fa有self有,3fa没有self有 
        dp[x][2]+=min(dp[y][0],dp[y][2]);
        dp[x][3]+=min(dp[y][0],dp[y][2]);
        if(dp[y][1]>dp[y][3]) sum++;
        else minn=min(minn,dp[y][3]-dp[y][1]);
        dp[x][0]+=min(dp[y][1],dp[y][3]);
        dp[x][1]+=min(dp[y][1],dp[y][3]);
    }
    if(!sum) dp[x][1]+=minn;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++){
        int ii,k;
        ii=read(),a[ii]=read(),k=read();
        for(int t=1;t<=k;t++){
            int y;
            y=read();
            add(ii,y),add(y,ii); 
        }
    }
    calc(1);
    cout<<min(dp[1][1],dp[1][3])<<endl;//根节点不会有父节点嘛,这个好理解
    return 0;
}

Guess you like

Origin www.cnblogs.com/DarkValkyrie/p/11210584.html