您的位置:首页 > 其它

[UVa1218]完美服务

2017-07-19 07:53 369 查看
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
, ecnt, sum;
struct node{ int e, next; }edge[N<<1];
long long dp
[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
, ecnt, sum;
struct node{ int e, next; }edge[N<<1];
bool vis
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  动态规划 贪心