题意:求一棵树的最小支配集
思路:dp
dp[u][0]表示u靠自己
dp[u][1]表示u靠父亲
dp[u][2]表示u靠儿子
v是u的儿子
dp[u][0]=sigma min(dp[v][0],min(dp[v][1],dp[v][2]))+1
dp[u][1]=sigma min(dp[v][0],dp[v][2]);
if 存在 dp[v][0]<=dp[v][2]
dp[u][2]=sigma min(dp[v][0],dp[v][2]);
else
dp[u][2]=min(dp[v][0]-dp[v][2])+sigma min(dp[v][0],dp[v][2]);
1 #include<iostream> 2 #include<cmath> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 #define MAXN 11000 7 struct node 8 { 9 int num; 10 node *next; 11 }; 12 node *graph[MAXN],memo[2*MAXN]; 13 int top=0,n; 14 int Q[MAXN],father[MAXN]; 15 int dp[MAXN][3];//0 靠自己 1靠父亲 2靠儿子 16 void add(int x,int y) 17 { 18 node *p=&memo[top++]; 19 p->num=y; p->next=graph[x]; graph[x]=p; 20 p=&memo[top++]; 21 p->num=x; p->next=graph[y]; graph[y]=p; 22 } 23 24 void solve() 25 { 26 int left,right,u,v,i; 27 Q[left=right=1]=1; 28 father[1]=0; 29 while(left<=right) 30 { 31 u=Q[left++]; 32 for(node *p=graph[u];p;p=p->next) 33 if(p->num!=father[u]) 34 Q[++right]=p->num,father[p->num]=u; 35 } 36 int s1,s2,s0,MIN; 37 for(i=right;i>0;i--) 38 { 39 s0=1; s1=s2=0; MIN=MAXN; 40 u=Q[i]; 41 for(node *p=graph[u];p;p=p->next) 42 if(p->num!=father[u]) 43 { 44 v=p->num; 45 s0+=min(dp[v][0],min(dp[v][1],dp[v][2])); 46 s1+=min(dp[v][0],dp[v][2]); 47 s2+=min(dp[v][0],dp[v][2]); 48 MIN=min(MIN,dp[v][0]-dp[v][2]); 49 } 50 if(MIN>0) s2+=MIN; 51 dp[u][0]=s0; dp[u][1]=s1; dp[u][2]=s2; 52 //cout<<u<<" "<<dp[u].first<<" "<<dp[u].second<<endl; 53 } 54 printf("%d\n",min(dp[1][0],dp[1][2])); 55 } 56 57 int main() 58 { 59 memset(dp,0,sizeof(dp)); 60 memset(graph,0,sizeof(graph)); 61 int x,y; 62 scanf("%d",&n); 63 for(int i=1;i<n;i++) 64 { 65 scanf("%d%d",&x,&y); 66 add(x,y); 67 } 68 solve(); 69 return 0; 70 }