[NOIP模拟赛]TPS

题目描述
Treelandn个城市,标号从1...n(1≤n≤5000)。有n-1条双向道路连接了n个城市构成一颗树。
Treeland的居民想要建造一套 TPS系统(Treeland Positioning System)TPS是一个能帮助人定位他在哪个城市的系统。系统由k个信号塔构成,每个信号塔被安放在一个城市。当一个人打开他的TPS接收器的时候他能得到他与每一个信号塔的距离(这里距离指树上两点之间经过的边的数量) 
显然只有当在不同的城市打开TPS接收器接受到的信息不一样的时候TPS系统才能正常工作。(也就不存在两个不同的城市使得在他们那里接收到的信号相同)注意不同的信号塔之间是可以区分的

求最少安放多少信号塔才能使TPS系统正常工作。


输入格式
1行:1个整数n,表示结点数
接下来n行,第i1个字符串,第j个字符为'Y',表示城市ij之间有一条道路。该字符为'N',则表示两个城市之间没有道路
 
输入样例
4
NYYY
YNNN
YNNN
YNNN
 
输出样例
2
 
样例说明
4个城市,道路图如下所示:
2 - 1 - 3
    |

    4

1个信号塔是不够的,因为如果它放置在城市1,那么城市234的距离都与那个信号塔有1距离,它们是无法区分的。如果它位于2号城市,那么34号城市都有2的距离,它们是无法区分的。

2个信号塔则足够了,因为如果把两个信号塔放置在城市23,那么:如果我们在城市1,接收器会显示距离1,1。如果我们在城市2,接收器将显示距离0,2。如果我们在城市3,接收器会显示距离2,0。如果我们在城市4,接收器会显示距离2,2

在每个城市里,接收器都显示出不同的距离序列。



题解

设f[i]为区分i子树内部的节点最少需要在i内部放置多少个信号塔(这里假设已经能区分一个节点是否在i子树内)。

若节点i两个不同的儿子ch1,ch2,在ch1,ch2子树内部均没有信号塔,那么这两个子树内部相同深度的节点无法区分。因此节点i最多只能有1个儿子满足以其为根的子树内没有信号塔。


#include<cstdio> 
#include<cstring> 
#include<algorithm> 
using namespace std; 
const int INF=0x3f3f3f3f; 
const int N=5005; 

int n, f[N][N], sum; 
bool map[N][N]; 
char ch[N]; 
  
void DFS( int r, int fa ) { 
    if( f[r][fa]<INF ) return; 
    bool flg=0; f[r][fa]=0; 
    for( int i=1; i<=n; i++ ) 
        if( i!=fa && map[r][i] ) { 
            DFS( i, r ); 
            f[r][fa]+=max( 1, f[i][r] ); 
            if( !f[i][r] ) flg=1; 
        } 
    f[r][fa]-=flg; 
} 
  
int main() {
	scanf( "%d", &n );
    for( int i=1; i<=n; i++ ) { 
        scanf( "%s", ch+1 ); 
        for( int j=1; j<=n; j++ ) 
            if( ch[j]=='Y' ) map[i][j]=1; 
    } 
    if( n<=1 ) { printf( "0\n" ); return 0; } 
    sum=n; 
    memset( f, 0x3f, sizeof f ); 
    for( int i=1; i<=n; i++ ) { 
        DFS( i, 0 );
        sum=min( sum, f[i][0]+1 ); 
    } 
    printf( "%d\n", sum ); 
    return 0; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值