#NOIP模擬賽#TSP(樹型DP)






這一題,枚舉根節點。

先貼上兩個性質:


定義Dp[u]表示以u爲根結點,保證u的子樹中所有節點都能被區分的最少信號塔數量。

因爲son已經保證了其子樹能被區分,所以只考慮u的直系子節點能否被區分。

如果有兩個及以上的子節點,那麼它們是不能被區分的,所以需要在u處放一個信號塔,從結論一得。

Code:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

const int Maxn = 5000;
const int Maxm = 5000;

struct node{
    int v, nxt;
}edge[(Maxm << 1) + 5];

int N, cnt;
int Dp[Maxn + 5], fir[Maxn + 5];
char S[Maxn + 5];

bool getint(int & num){
    char c; int flg = 1;    num = 0;
    while((c = getchar()) < '0' || c > '9'){
        if(c == '-')    flg = -1;
        if(c == -1) return 0;
    }
    while(c >= '0' && c <= '9'){
        num = num * 10 + c - 48;
        if((c = getchar()) == -1)   return 0;
    }
    num *= flg;
    return 1;
}

void addedge(int a, int b){
    edge[++ cnt].v = b, edge[cnt].nxt = fir[a], fir[a] = cnt;
}

void Get_Dp(int u, int fa){
    Dp[u] = 0;
    int tot = 0;
    for(int i = fir[u]; i; i = edge[i].nxt) if(edge[i].v != fa){
        int v = edge[i].v;
        Get_Dp(v, u);
        if(! Dp[v]) ++ tot;
        else Dp[u] += Dp[v];
    }
    if(tot) Dp[u] += tot - 1;
}

int main(){
    //freopen("tps.in", "r", stdin);
    //freopen("tps.out", "w", stdout);
    getint(N);
    for(int i = 1; i <= N; ++ i){
        scanf("%s", S + 1);
        for(int j = 1; j <= N; ++ j)    if(S[j] == 'Y')
            addedge(i, j);
    }
    int Ans = N;
    for(int Root = 1; Root <= N; ++ Root){
        Get_Dp(Root, 0);
        Ans = min(Dp[Root] + 1, Ans);
    }
    printf("%d\n", Ans);
    return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章