[51nod1314] 定位系统

 

题意:给你一棵树,要求你选择一些点建立信号站,使得每一个点到这些信号站的距离数组dis都不一样(注意是数组不一样)

 

题解:

树形dp

1、若在两点x,y建立信号站,那么x->y路径上的所有点的dis数组都不一样

2、考虑选择一个点为根并标记,那么尽量选择叶子标记,这样链越长,贡献越大

3、若某个结点的子树为多叉树,那么至多可以有一条链形子树的叶子不需要标记,因为这条链上的结点可以被其他子树标记的点影响

4、特判:n=1时,答案为0。当树退化成链时,当前的根节点不需要标价

 

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define ll long long
#define N 55
using namespace std;

int e_num,dp[N],t[N],nxt[N*2],to[N*2],h[N];
char s[55];

int gi() {
  int x=0,o=1; char ch=getchar();
  while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
  if(ch=='-') o=-1,ch=getchar();
  while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
  return o*x;
}

void add(int x, int y) {
  nxt[++e_num]=h[x],to[e_num]=y,h[x]=e_num;
}

void dfs(int u, int fa) {
  dp[u]=0,t[u]=0;
  int flg=0;
  for(int i=h[u]; i; i=nxt[i]) {
    int v=to[i];
    if(v==fa) continue;
    if(!t[u]) t[u]=1;
    else t[u]=2;
    dfs(v,u);
    dp[u]+=dp[v];
    if(t[v]<=1) flg=1;//有一个子树为链
    else if(t[v]) t[u]=2;//表示它并非一条链的形式
  }
  if(t[u]==2) dp[u]-=flg;
  if(!t[u]) dp[u]=1;
}

int main() {
  int n=gi(),ans=1<<30; 
  if(n==1) {puts("0");return 0;}
  for(int i=1; i<=n; i++) {
    scanf("%s", s+1);
    for(int j=1; j<=n; j++) {
      if(s[j]=='Y') add(i,j);
    }
  }
  for(int i=1; i<=n; i++) {
    dfs(i,0);
    dp[i]+=(t[i]==2);
    ans=min(ans,dp[i]);
  }
  printf("%d", ans);
  return 0;
}

 

posted @ 2017-09-26 16:48  HLX_Y  阅读(175)  评论(0编辑  收藏  举报