• POJ3659 Cell Phone Network(树上最小支配集:树型DP)


    题目求一棵树的最小支配数。

    支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻。

    听说即使是二分图,最小支配集的求解也是还没多项式算法的。而树上求最小支配集树型DP就OK了。

    树上的每个结点作为其子树的根可以有三个状态:

    1. 不属于支配集且还没被支配
    2. 不属于支配集但被其孩子支配
    3. 属于支配集

    那么就是用dp[u][123]来作为动归的状态,表示结点u为根子树的且u状态为1、2、3的最小支配数。

    123转移该怎么转移就怎么转移。。最后的结果就是min(dp[root][2],dp[root][3])。

    要注意的是对于有些结点前2个状态可能是不存在的,比如叶子结点不存在第2个状态、存在孩子是叶子结点的结点不存在第1个状态,这些不存在的状态要在转移的时候处理。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 #define INF 123456
     6 #define MAXN 111111
     7 struct Edge{
     8     int u,v,next;
     9 }edge[MAXN<<1];
    10 int NE,head[MAXN];
    11 void addEdge(int u,int v){
    12     edge[NE].u=u; edge[NE].v=v; edge[NE].next=head[u];
    13     head[u]=NE++;
    14 }
    15 int d[MAXN][3];
    16 int dp(int u,int k,int fa){
    17     if(d[u][k]!=-1) return d[u][k];
    18     int res=0,diff=INF; bool flag=0,isLeaf=1;
    19     for(int i=head[u]; i!=-1; i=edge[i].next){
    20         int v=edge[i].v;
    21         if(v==fa) continue;
    22         isLeaf=0;
    23         if(k==0){
    24             if(dp(v,1,u)==INF) return d[u][k]=INF;
    25             res+=dp(v,1,u);
    26         }else if(k==1){
    27             if(dp(v,2,u)<=dp(v,1,u)){
    28                 res+=dp(v,2,u);
    29                 flag=1;
    30             }else{
    31                 if(dp(v,1,u)==INF) return d[u][k]=INF;
    32                 res+=dp(v,1,u);
    33                 diff=min(diff,dp(v,2,u)-dp(v,1,u));
    34             }
    35         }else{
    36             res+=min(min(dp(v,0,u),dp(v,1,u)),dp(v,2,u));
    37         }
    38     }
    39     if(k==1 && isLeaf) return d[u][k]=INF;
    40     if(k==1 && !flag) res+=diff;
    41     return d[u][k]=res+(k==2);
    42 }
    43 int main(){
    44     int n,a,b;
    45     scanf("%d",&n);
    46     NE=0;
    47     memset(head,-1,sizeof(head));
    48     for(int i=1; i<n; ++i){
    49         scanf("%d%d",&a,&b);
    50         addEdge(a,b); addEdge(b,a);
    51     }
    52     memset(d,-1,sizeof(head));
    53     printf("%d",min(dp(1,1,0),dp(1,2,0)));
    54     return 0;
    55 }
  • 相关阅读:
    [UVA 10603]Fill
    [BZOJ 4152][AMPPZ 2014]The Captain
    P4779单源最短路径(标准版)
    P3372 线段树模版1
    P1776宝物筛选
    最长上升子序列模版
    01背包问题
    SHOI2008 汉诺塔
    log P1080国王游戏
    最小生成树模版 Kruskal
  • 原文地址:https://www.cnblogs.com/WABoss/p/5186593.html
Copyright © 2020-2023  润新知