pku3659 Cell Phone Network

http://poj.org/problem?id=3659

树状DP,树的最小点覆盖

  1 #include <stdio.h>
  2 #include <vector>
  3 #define N 10010
  4 
  5 using namespace std;
  6 
  7 vector<int> a[N];
  8 int mark[N], dp[N][3];
  9 const int inf = 12345678;
 10 
 11 int min(int x, int y)
 12 {
 13     return x<y? x: y;
 14 }
 15 
 16 int limit_inf(int x)
 17 {
 18     return x>inf? inf: x;
 19 }
 20 
 21 int f(int x, vector<int> b)
 22 {
 23     int i, j, k, sum1, min1;
 24 
 25     //leaf
 26     if(b.size() == 0)
 27     {
 28         dp[x][0] = 0;
 29         dp[x][1] = inf;
 30         dp[x][2] = 1;
 31         return 0;
 32     }
 33     
 34     //0
 35     sum1 = 0;
 36     for(i=0; i<b.size(); i++)
 37     {
 38         sum1 += dp[b[i]][1];
 39     }
 40     dp[x][0] = limit_inf(sum1);
 41 
 42     //1
 43     min1 = inf;
 44     for(i=0; i<b.size(); i++)
 45     {
 46         sum1 = dp[b[i]][2];
 47         for(j=0; j<b.size(); j++)
 48         {
 49             if(j != i)
 50             {
 51                 sum1 += min(dp[b[j]][1], dp[b[j]][2]);
 52             }
 53         }
 54         min1 = min(min1, sum1);
 55     }
 56     dp[x][1] = limit_inf(min1);
 57 
 58     //2
 59     sum1 = 0;
 60     for(i=0; i<b.size(); i++)
 61     {
 62         sum1 += min(dp[b[i]][0], min(dp[b[i]][1], dp[b[i]][2]));
 63     }
 64     sum1 += 1;
 65     dp[x][2] = limit_inf(sum1);
 66     return 0;
 67 }
 68 
 69 int dfs(int x)
 70 {
 71     int i, j;
 72     vector<int> b;
 73     b.clear();
 74     //printf("(%d: ", x);
 75     for(i=0; i<a[x].size(); i++) 
 76     {
 77         j = a[x][i];
 78         if(mark[j] == 0)
 79         {
 80             b.push_back(j);
 81             mark[j] = 1;
 82             dfs(j);
 83         }
 84     }
 85     f(x, b);
 86     //printf("[%d,%d,%d]", dp[x][0], dp[x][1], dp[x][2]);
 87     //printf(" ) ");
 88     return 0;
 89 }
 90 
 91 int main()
 92 {
 93     int n, i, x, y;
 94     while(~scanf("%d", &n))
 95     {
 96         for(i=1; i<=n; i++)
 97         {
 98             //dp[i][0] = dp[i][1] = dp[1][2] = inf;
 99             mark[i] = 0;
100             a[i].clear();
101         }
102         for(i=1; i<=n-1; i++)
103         {
104             scanf("%d%d", &x, &y);
105             a[x].push_back(y);
106             a[y].push_back(x);
107         }
108         mark[1] = 1;
109         dfs(1);
110         printf("%d\n", min(dp[1][1], dp[1][2]));
111         if(dp[1][2] == inf)
112         {
113             dp[1][2] = -1;
114         }
115         //printf("\n");
116         //for(i=1; i<=n; i++)
117         //{
118         //   printf("%5d %5d %5d\n", dp[i][0], dp[i][1], dp[i][2]);
119         //}
120     }
121     return 0;
122 }

 

转载于:https://www.cnblogs.com/yuan1991/p/pku3659.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值