SPOJ 1435 Vertex Cover 树形DP

i 表示节点 i ,j=0表示不选择其父节点,j=1表示选择其父节点。f 为其父节点。

取 每个节点选择/不选择 两者中较小的那个。

一组数据:

15
1 2
1 3
1 4
1 10
10 9
10 11
12 10
12 14
10 13
13 15
4 5
5 7
4 6
6 8

答案是6

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <algorithm>
 5 #include <vector>
 6 
 7 using namespace std;
 8 
 9 const int MAXN = 100010;
10 
11 vector<int> adj[MAXN];
12 bool vis[MAXN][2];
13 int d[MAXN][2];
14 int n, m;
15 //int path[MAXN][2];
16 //int fang[MAXN];
17 
18 int dp( int i, int j, int f )
19 {
20     if ( vis[i][j] ) return d[i][j];
21     vis[i][j] = true;
22     int &ans = d[i][j];
23 
24     ans = 1;
25     for ( int k = 0; k < (int)adj[i].size(); ++k )
26     if ( adj[i][k] != f ) ans += dp( adj[i][k], 1, i );
27     //path[i][j] = f;
28 
29     if ( j || f < 0 )
30     {
31         int sum = 0;
32         for ( int k = 0; k < (int)adj[i].size(); ++k )
33         if ( adj[i][k] != f )
34            sum += dp( adj[i][k], 0, i );
35         if ( sum < ans )
36         {
37             ans = sum;
38             //path[i][j] = -f;
39         }
40     }
41     return ans;
42 }
43 
44 //void DFS( int i, int j, int f )
45 //{
46 //    if ( fang[i] != -1 ) return;
47 //    if ( !path[i][j] || path[i][j] == f )
48 //    {
49 //        if ( f >= 0 ) fang[f] = j;
50 //        for ( int k = 0; k < (int)adj[i].size(); ++k )
51 //            if ( adj[i][k] != f ) DFS( adj[i][k], 1, i );
52 //    }
53 //    else
54 //    {
55 //        if ( f >= 0 ) fang[f] = j;
56 //        for ( int k = 0; k < (int)adj[i].size(); ++k )
57 //            if ( adj[i][k] != f ) DFS( adj[i][k], 0, i );
58 //
59 //    }
60 //    return;
61 //}
62 
63 int main()
64 {
65     while ( ~scanf( "%d", &n ) )
66     {
67         m = n - 1;
68         for ( int i = 0; i <= n; ++i ) adj[i].clear();
69 
70         for ( int i = 0; i < m; ++i )
71         {
72             int a, b;
73             scanf( "%d%d", &a, &b );
74             adj[a].push_back(b);
75             adj[b].push_back(a);
76         }
77 
78         memset( vis, false, sizeof(vis) );
79         //memset( fang, -1, sizeof(fang) );
80         //memset( path, 0, sizeof(path) );
81 
82         int ans = dp( 1, 0, -1 );
83         printf( "%d\n", ans );
84     }
85     return 0;
86 }

 

转载于:https://www.cnblogs.com/GBRgbr/p/3210449.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值