(树形DP) poj 3398

Perfect Service

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 1393   Accepted: 679

Description

A network is composed of N computers connected by N − 1 communication links such that any two computers can be communicated via a unique route. Two computers are said to be adjacent if there is a communication link between them. The neighbors of a computer is the set of computers which are adjacent to it. In order to quickly access and retrieve large amounts of information, we need to select some computers acting as servers to provide resources to their neighbors. Note that a server can serve all its neighbors. A set of servers in the network forms a perfect service if every client (non-server) is served byexactly one server. The problem is to find a minimum number of servers which forms a perfect service, and we call this number perfect service number.

We assume that N (≤ 10000) is a positive integer and these N computers are numbered from 1 to N. For example, Figure 1 illustrates a network comprised of six computers, where black nodes represent servers and white nodes represent clients. In Figure 1(a), servers 3 and 5 do not form a perfect service because client 4 is adjacent to both servers 3 and 5 and thus it is served by two servers which contradicts the assumption. Conversely, servers 3 and 4 form a perfect service as shown in Figure 1(b). This set also has the minimum cardinality. Therefore, the perfect service number of this example equals two.

Your task is to write a program to compute the perfect service number.

Input

The input consists of a number of test cases. The format of each test case is as follows: The first line contains one positive integer, N, which represents the number of computers in the network. The next N − 1 lines contain all of the communication links and one line for each link. Each line is represented by two positive integers separated by a single space. Finally, a 0 at the (N + 1)th line indicates the end of the first test case.

The next test case starts after the previous ending symbol 0. A −1 indicates the end of the whole inputs.

Output

The output contains one line for each test case. Each line contains a positive integer, which is 
the perfect service number.

Sample Input

6
1 3
2 3
3 4
4 5
4 6
0
2
1 2
-1

Sample Output

2
1

Source

题意】:给出一棵树,每个节点代表一台电脑,现在需要选择一些电脑作为服务器。如果一台电脑被选作服务器,那么它和和它相邻的电脑都会被激活,非服务器的电脑不能同时被多台服务器激活。问最少要选多少台电脑作为服务器使得所有电脑被激活。

【题解】:树dp,树的最小支配集变形。
               设状态
                  dp[u][0] 以u为根且u为服务器且整棵子树都被激活的最小代价。
                  dp[u][1] 以u为根且u被某个儿子结点激活且整棵子树都被激活的最小代价。
                  dp[u][2] 以u为根且u被父亲结点激活且整棵子树都被激活的最小代价。
 
               转移 (v 为 u 的儿子)
                  dp[u][0] = ∑min(dp[v][0], dp[v][2]) + 1;
                  dp[u][1] = min(sum - dp[v][1] + dp[v][0]), sum = ∑dp[v][1];
                  dp[u][2] = ∑dp[v][1];
               
               任取一个结点为root进行树dp, ans = min(dp[root][0], dp[root][1]).

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<string>
#include<algorithm>
#include<queue>
#include<vector>
#define INF 100000000
using namespace std;
vector<int> e[10005];
int n,dp[10005][3];
void init()
{
    for(int i=1;i<=n;i++)
        e[i].clear();
}
void dfs(int u,int father)
{
    dp[u][0]=1;
    dp[u][1]=INF;
    dp[u][2]=0;
    for(int i=0;i<e[u].size();i++)
    {
        int v=e[u][i];
        if(v==father)
            continue;
        dfs(v,u);
        dp[u][0]+=min(dp[v][0],dp[v][2]);
        dp[u][2]+=dp[v][1];
    }
    for(int i=0;i<e[u].size();i++)
    {
        int v=e[u][i];
        if(v==father)
            continue;
        dp[u][1]=min(dp[u][2]-dp[v][1]+dp[v][0],dp[u][1]);
    }
}
int main()
{
    int temp;
    while(scanf("%d",&n)!=EOF)
    {
        init();
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            e[x].push_back(y);
            e[y].push_back(x);
        }
        dfs(1,-1);
        printf("%d\n",min(dp[1][0],dp[1][1]));
        scanf("%d",&temp);
        if(temp==-1)
            break;
    }
    return 0;
}

  

时间: 2024-10-14 00:30:02

(树形DP) poj 3398的相关文章

树形dp poj 2342

题目链接:poj 2342 题目大意:某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知每个人的活跃指数和上司关系(当然不可能存在环),求邀请哪些人(多少人)来能使得晚会的总活跃指数最大. 思路:既然是树形dp,自然先建立一颗树了,这里用的是邻接表(L<-K).找根的时候利用flag数组来标记所有儿子节点,那么没有标记的自然是根节点了.树形dp从叶子节点开始dp,所以深搜到叶子节点,然后不断回溯给父节点.在处理儿子节点时,父节点不参加

树形DP [POJ 1155] TELE

TELE Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3787   Accepted: 2007 Description A TV-network plans to broadcast an important football match. Their network of transmitters and users can be represented as a tree. The root of the tre

树形DP [POJ 1947] Rebuilding Roads

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9249   Accepted: 4198 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The

(树形DP) poj 3659

Cell Phone Network Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5916   Accepted: 2119 Description Farmer John has decided to give each of his cows a cell phone in hopes to encourage their social interaction. This, however, requires hi

POJ 3398 / UVA 1218 Perfect Service 树形DP

树形DP Perfect Service Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 1378   Accepted: 668 Description A network is composed of N computers connected by N ? 1 communication links such that any two computers can be communicated via a uniqu

poj 3342(树形dp)

题意:在一个公司中要举办一个聚会,每一个员工有一个奉献值.为了和谐规定直接上下级不能一起出席.让你找出奉献值之和最大为多少. 思路:dp[v][1]表示当前结点选,能获得的最大奉献值,dp[v][0]表示当前节点不选能获得的最大奉献值.状态转移: dp[v][0] = max(dp[v][0], ∑max(dp[x][1], dp[x][0]))x为直接儿子 dp[v][1] = max(dp[v][1], ∑dp[x][0] + vex[v]) 最后答案是max(dp[root][0], dp

poj 4045 Power Station(初涉树形dp)

http://poj.org/problem?id=4045 大致题意:有n个村庄,求将发电站建在哪一个村庄使得花费最少.这是一个无向无环图.简化一下就是求一个节点使它到其他所有节点的距离和最小. 起初一直在向最短路上靠,但因为节点和边数太大,必定TLE.然后无比强大的啸神随便写了两个dfs就过掉了,简直膜拜.赛后搜了搜题解,发现这是道树形dp.sad,真的要好好刷dp了. 大体思路是将这个无向无环图看做一个树,我们就在这个树上进行动态规划.首先先随便拿一个节点看做根节点(假设节点1),计算出它

poj 1655 and 3107 and 2378 树形dp(树的重心问题)

简单的树形dp,顺便学习了树的重心的概念,即以该点为根的树的最大子树的结点数最少. poj 1655: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 20001; 7 int head[N]; 8 int balance[N]; 9 int child[N]; 10 int n, e; 11 12 struct

[POJ 1947]Rebuilding Roads (树形dp)

题目链接:http://poj.org/problem?id=1947 题目大意:给你一棵树,树上N个节点.问最少拆掉多少条边使得存在一个联通块,有P个节点. 树形dp,设计状态:dp[u][i]代表以u为根节点的剩下i个节点最少需要拆掉多少条边. 状态转移:dp[u][i+j] = min(dp[u][i+j],dp[u][i]+dp[v][j]-1); 其中v是u的儿子节点. 相当于在树上跑01背包,即每个儿子节点去掉剩下j个的但是要连上u-v边,或者不去掉剩下j个的. 代码: 1 impo