0.0

###### Poj 3659 Perfect Service【最小支配集、树型dp】

Perfect Service

 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 1499 Accepted: 726

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 by exactly 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

Kaohsiung 2006

1、首先既然是dp问题，首先我们要设计dp的数组和其含义：

dp【u】【0】表示点u属于支配集，并且以u为根节点的子树已经全部被覆盖。

dp【u】【1】表示点u不属于支配集，并且以u为根节点的子树已经全部覆盖，并且点u被至少其一个子节点所支配。

dp【u】【2】表示点u不属于支配集，并且以u为根节点的子树已经全部覆盖，并且点u没有被其子节点所支配。（那么不难理解，这个点要被其父节点所支配）

2、对数组进行设计完毕之后，我们就要来考虑状态转移过程，分别讨论三种dp数组是如何转移过来：

dp【u】【0】：dp【u】【0】表示点u属于支配集，但是其子节点不能被两个点覆盖，所以这种情况下，其子节点要么是属于支配集的点，要么是没有被其子节点的子节点有所覆盖的点，辣么不难理解其状态转移方程为：

dp【u】【0】+=1+枚举所有子节点min（dp【v】【0】，dp【v】【2】）

dp【u】【1】：dp【u】【1】表示点u不属于支配集，但是点u被支配着，所以其支配来源一定是从子节点来的，只要其子节点中只要有一个节点属于支配集，那么当前节点u就会被支配，也就是说以u为根节点的子树包含u在内，所有节点都背覆盖了，达到目的。那么不难理解，dp【u】【1】的来源可能是dp【v】【0】或者是dp【v】【1】，并且满足至少一个来源是dp【v】【0】即可。

dp【u】【1】=INF；

dp【u】【1】+=枚举所有子节点min（dp【v】【0】，dp【v】【1】）//并且保证其状态转移过程中至少有一个来源于dp【v】【0】，具体参考代码实现。

dp【u】【2】：dp【u】【2】表示点u不属于支配集，并且点u不被其任一子节点所支配，那么其来源就只能是dp【v】【1】或者是dp【v】【2】，但是如果来源是dp【v】【2】的话，那么我们就不能保证两个节点被同时支配了，所以dp【u】【2】只能来源于dp【v】【1】。

d辣么其状态转移方程：
dp【u】【2】+=枚举所有子节点dp【v】【1】；其中任一dp【v】【1】==INF，那么dp【u】【2】=INF。

3、根节点的确定：我们不妨建立成双向图，那么任何一个点都可以做为根节点向下递归求解。

AC代码：

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define INF 0x1f1f1f1f
struct EdgeNode
{
int to;
int w;
int next;
}e[100000];
int cont;
int dp[5000000][3];
int vis[500000];
{
e[cont].to=to;
e[cont].to=from;
}
void Dp(int u)
{
dp[u][2]=0;
dp[u][1]=0;
dp[u][0]=1;
int sum=0,inc=INF;
vis[u]=1;
bool judge=false;
{
int to=e[k].to;
if(vis[to]==1)continue;
Dp(to);
dp[u][0]+=min(dp[to][0],dp[to][2]);
if(dp[to][0]<=dp[to][1])
{
sum+=dp[to][0];
judge=true;
}
else
{
sum+=dp[to][1];
inc=min(inc,dp[to][0]-dp[to][1]);
}
if(dp[to][1]!=INF&&dp[u][2]!=INF)dp[u][2]+=dp[to][1];
else dp[u][2]=INF;
}
if(inc==INF&&judge==false)dp[u][1]=INF;
else
{
dp[u][1]=sum;
if(judge==false)dp[u][1]+=inc;
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
memset(dp,0,sizeof(dp));
cont=0;
for(int i=0;i<n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
}
int op;
scanf("%d",&op);
Dp(1);
printf("%d\n",min(min(dp[1][0],dp[1][1]),dp[1][2]+1));
if(op==-1)break;
}
}


#### POJ3659 Cell Phone Network【最小支配集】【贪心】

2015-01-01 14:04:46

#### poj 3659 Cell Phone Network 树型DP也是树的最小支配集

2012-08-17 17:34:03

#### POJ 3659 Cell Phone Network【最小支配集、树型dp】

2016-05-25 13:22:00

#### POJ 3659 贪心 最小支配集

2015-05-14 11:12:38

#### POJ 3659 树形DP，最小支配集

2015-05-14 11:13:42

#### POJ 3659 树图的最小支配集

2012-09-01 15:29:27

#### POJ 1274 The Perfect Stall （网络流-最大流）

2014-08-06 16:08:12

#### poj 3659 树形dp 最小支配集

2013-10-25 21:36:28

#### POJ 3398 Perfect Service 最小支配集变形

2013-10-18 14:46:09

#### POJ 3398 Perfect Service【最小支配集修改 dp】

2016-05-18 21:36:29

## 不良信息举报

Poj 3659 Perfect Service【最小支配集、树型dp】