• [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 }
    代码在这里!

  • 相关阅读:
    python项目实战三个小实例
    Python关键字及其用法
    python目录和文件的列表清单
    python文件的分类
    python文件操作r+,w+,a+,rb+,
    Python初探list
    python列表1
    office之Excel 你会用 Ctrl + E 吗?
    java用swing画可以行走的乌龟
    python删除列表元素
  • 原文地址:https://www.cnblogs.com/wuliking/p/11264374.html
Copyright © 2020-2023  润新知