1. 程式人生 > >[51nod1314] 定位系統

[51nod1314] 定位系統

turn code 信號 stream 51nod i++ 題解 class ret

題意:給你一棵樹,要求你選擇一些點建立信號站,使得每一個點到這些信號站的距離數組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; }

[51nod1314] 定位系統