• [UVA-1218] Perfect Service(树的最小支配集)


    题目链接:https://vjudge.net/problem/UVA-1218

    题目大意:给你一棵无向树,让你求树的最小支配集,但是有一个要求是除最小支配集外剩下的任何一个结点不能同时连接支配集中的两个元素

    解题报告:采用树形dp,只需将第一种状态的状态转移方程修改为$dp[i][0] = 1+sum_{ p[u]=i }min(dp[u][0],dp[u][2])$

    AC代码:

     1 #include<vector>
     2 #include<cstdio>
     3 #include<iostream>
     4 #include<cmath>
     5 #include<queue>
     6 #include<stack>
     7 #define numm ch-48
     8 #define pd putchar(' ')
     9 #define pn putchar('
    ')
    10 #define pb push_back
    11 #define fi first
    12 #define se second
    13 #define fre1 freopen("1.txt","r",stdin)
    14 #define fre2 freopen("2.txt","w",stdout)
    15 using namespace std;
    16 template <typename T>
    17 void read(T &res) {
    18     bool flag=false;char ch;
    19     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    20     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    21     flag&&(res=-res);
    22 }
    23 template <typename T>
    24 void write(T x) {
    25     if(x<0) putchar('-'),x=-x;
    26     if(x>9) write(x/10);
    27     putchar(x%10+'0');
    28 }
    29 const int maxn=10010;
    30 const int N=1010;
    31 const int inf=0x3f3f3f3f;
    32 const int INF=0x7fffffff;
    33 typedef long long ll;
    34 struct node {
    35     int v,net;
    36 }e[maxn<<1];
    37 int cnt,n,head[maxn];
    38 int dp[maxn][3];
    39 void add(int u,int v) {
    40     e[++cnt].v=v;
    41     e[cnt].net=head[u];
    42     head[u]=cnt;
    43 }
    44 void DP(int u,int p) {  ///u:当前结点,p:u的父结点
    45     bool flag=false;    ///标记是否有一个dp[to][0]<=dp[to][1]
    46     int sum=0,inc=INF;
    47     dp[u][2]=0; ///第三状态,当前结点未被选中
    48     dp[u][0]=1; ///第一状态,当前结点被选中,dp[u][0]+1
    49     for(int i=head[u];i!=-1;i=e[i].net) {
    50         int to=e[i].v;
    51         if(to==p) continue; ///to必须是u的子节点,不是父节点(由根dp到叶子)
    52         DP(to,u);   ///dp子节点
    53         dp[u][0]+=min(dp[to][0],dp[to][2]);  ///回溯,第一状态的转移
    54         if(dp[to][0]<=dp[to][1]) {  ///第二状态的判断
    55             flag=true;
    56             sum+=dp[to][0];
    57         }
    58         else {
    59             sum+=dp[to][1];
    60             inc=min(inc,dp[to][0]-dp[to][1]);
    61         }
    62         if(dp[to][1]!=INF&&dp[u][2]!=INF)    ///第三状态的转移
    63             dp[u][2]+=dp[to][1];
    64         else dp[u][2]=INF;  ///根据定义dp[u][2]=(dp[to][1]的总和)
    65     }
    66     if(!flag&&inc==INF) ///判断当前是不是叶子结点
    67         dp[u][1]=INF;
    68     else
    69         dp[u][1]=sum+(flag?0:inc);
    70 }
    71 int main()
    72 {
    73     while(scanf("%d",&n)!=EOF&&n) {
    74         for(int i=1;i<=n;i++)
    75             head[i]=-1,dp[i][0]=dp[i][1]=dp[i][2]=0,cnt=0;
    76         for(int i=1;i<=n-1;i++) {
    77             int a,b;
    78             read(a),read(b);
    79             add(a,b);
    80             add(b,a);
    81         }
    82         DP(1,1);
    83         write(min(dp[1][0],dp[1][1]));pn;
    84         int flag;
    85         read(flag);
    86         if(flag==-1) break;
    87     }
    88     return 0;
    89 }
    代码在这里!

  • 相关阅读:
    DOM属性(childNodes, nodeType, nodeValue, nodeName, firstChild, lastChild)
    ImageCopyResampled和ImageCopyResized区别
    Js中 关于top、clientTop、scrollTop、offsetTop等
    js笔记之Math random()、ceil()、floor()、round()
    linux下软件安装
    风云的博客地址
    hasOwnProperty 方法
    Javascript的匿名函数
    [转载]JS拖动技术 关于setCapture
    利用jquery的imgAreaSelect插件实现图片裁剪示例
  • 原文地址:https://www.cnblogs.com/wuliking/p/11264374.html
Copyright © 2020-2023  润新知