[UVa1218]完美服务

来源:互联网 发布:linux虚拟机网络配置 编辑:程序博客网 时间:2024/05/16 07:54

A network is composed of N computers connected by N − 1 communication links such that any twocomputers can be communicated via a unique route. Two computers are said to be adjacent if there isa communication link between them. The neighbors of a computer is the set of computers which areadjacent to it. In order to quickly access and retrieve large amounts of information, we need to selectsome computers acting as servers to provide resources to their neighbors. Note that a server can serveall its neighbors. A set of servers in the network forms a perfect service if every client (non-server) isserved by exactly one server. The problem is to find a minimum number of servers which forms aperfect 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 toN. For example, Figure 1 illustrates a network comprised of six computers, where black nodes representservers and white nodes represent clients. In Figure 1(a), servers 3 and 5 do not form a perfect servicebecause client 4 is adjacent to both servers 3 and 5 and thus it is served by two servers which contradictsthe assumption. Conversely, servers 3 and 4 form a perfect service as shown in Figure 1(b). This setalso 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 linecontains 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 representedby two positive integers separated by a single space. Finally, a ‘0’ at the (N + 1)-th line indicates theend of the first test case.

The next test case starts after the previous ending symbol ‘0’. A ‘-1’ indicates the end of the wholeinputs.

Output

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

Sample Input

6

1 3

2 3

3 4

4 5

4 6

0

2

1 2

-1

Sample Output

2

1


题意:

有n(n≤10000)台机器形成树状结构。要求在其中一些机器上安装服务器,使得每台不是服务器的计算机恰好和一台服务器计算机相邻,求服务器的最少数量。


题解1:dp

定义:

dp[i][0]: i是服务器, i的子结点可以是服务器也可以不是

dp[i][1]: i不是服务器, 但i的父亲是服务器

dp[i][2]: i和i的父亲都不是服务器


状态转移方程: 

dp[i][0]=sum{ min(dp[son][0], dp[son][1]) }+1;

dp[i][1]=sum{ dp[son][2] };

dp[i][2]=min( dp[i][2], dp[son][0]+dp[i][1]-dp[son][2] );


分析: 

dp[i][0]: i已经是服务器, 所以子结点可以是也可以不是, 选择小的, +1代表i自身这个服务器;


dp[i][1]: i不是服务器, 但i的父亲是服务器, 则i的所有子结点不可能是服务器, 否则i就连了两个服务器, 非最优解;


dp[i][2]: i和i的父亲都不是服务器, 则i有且仅有一个子结点是服务器, 否则i就未连服务器或连多个服务器, 

dp[i][2]=min( dp[i][2], dp[son][0]+sum{ dp[otherson][2] } ), 状态二已算出dp[son][2]的和, 可以简化.

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>using namespace std;const int INF=0x3f3f3f3f;const int N=1e4+10;int n, fir[N], ecnt, sum;struct node{ int e, next; }edge[N<<1];long long dp[N][3];void Link( int s, int e ) {edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt;edge[++ecnt].e=s; edge[ecnt].next=fir[e]; fir[e]=ecnt;}void DFS( int r, int fa ) {bool flg=0;dp[r][0]=1;dp[r][1]=0;dp[r][2]=INF;for( int i=fir[r]; i; i=edge[i].next )if( edge[i].e!=fa ) {DFS( edge[i].e, r );flg=1;dp[r][0]+=min( dp[edge[i].e][0], dp[edge[i].e][1] );dp[r][1]+=dp[edge[i].e][2];}if( !flg ) return;for( int i=fir[r]; i; i=edge[i].next )if( edge[i].e!=fa )dp[r][2]=min( dp[r][2], dp[edge[i].e][0]+dp[r][1]-dp[edge[i].e][2] );}void Reset() {ecnt=0;memset( fir, 0, sizeof fir );}int main() {while( ~scanf( "%d", &n ) ) {if( !n ) continue;if( n==-1 ) break;Reset();for( int i=1; i<n; i++ ) {int s, e;scanf( "%d%d", &s, &e );Link( s, e );}DFS( 1, -1 );printf( "%lld\n", min( dp[1][0], dp[1][2] ) );}return 0;}

题解2:贪心

如果一个点的所有儿子及其自己都不是服务器,那就让他的父亲节点成为服务器

#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<cmath>#include<algorithm>using namespace std;const int N=1e4+10;int n, fir[N], ecnt, sum;struct node{ int e, next; }edge[N<<1];bool vis[N];void Link( int s, int e ) {edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt;edge[++ecnt].e=s; edge[ecnt].next=fir[e]; fir[e]=ecnt;}void DFS( int r, int fa ) {bool flg=0;for( int i=fir[r]; i; i=edge[i].next )if( edge[i].e!=fa ) {DFS( edge[i].e, r );if( vis[edge[i].e] ) flg=1;}if( !flg && !vis[r] && !vis[fa] ) sum++, vis[fa]=1;}void Reset() {sum=ecnt=0;memset( vis, 0, sizeof vis );memset( fir, 0, sizeof fir );}int main() {while( ~scanf( "%d", &n ) ) {if( !n ) continue;if( n==-1 ) break;Reset();for( int i=1; i<n; i++ ) {int s, e;scanf( "%d%d", &s, &e );Link( s, e );}DFS( 1, -1 );printf( "%d\n", sum );}return 0;}

原创粉丝点击