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
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector> using namespace std; const int MAXN = ; vector<int> adj[MAXN];
bool vis[MAXN][];
int d[MAXN][];
int n, m;
//int path[MAXN][2];
//int fang[MAXN]; int dp( int i, int j, int f )
{
if ( vis[i][j] ) return d[i][j];
vis[i][j] = true;
int &ans = d[i][j]; ans = ;
for ( int k = ; k < (int)adj[i].size(); ++k )
if ( adj[i][k] != f ) ans += dp( adj[i][k], , i );
//path[i][j] = f; if ( j || f < )
{
int sum = ;
for ( int k = ; k < (int)adj[i].size(); ++k )
if ( adj[i][k] != f )
sum += dp( adj[i][k], , i );
if ( sum < ans )
{
ans = sum;
//path[i][j] = -f;
}
}
return ans;
} //void DFS( int i, int j, int f )
//{
// if ( fang[i] != -1 ) return;
// if ( !path[i][j] || path[i][j] == f )
// {
// if ( f >= 0 ) fang[f] = j;
// for ( int k = 0; k < (int)adj[i].size(); ++k )
// if ( adj[i][k] != f ) DFS( adj[i][k], 1, i );
// }
// else
// {
// if ( f >= 0 ) fang[f] = j;
// for ( int k = 0; k < (int)adj[i].size(); ++k )
// if ( adj[i][k] != f ) DFS( adj[i][k], 0, i );
//
// }
// return;
//} int main()
{
while ( ~scanf( "%d", &n ) )
{
m = n - ;
for ( int i = ; i <= n; ++i ) adj[i].clear(); for ( int i = ; i < m; ++i )
{
int a, b;
scanf( "%d%d", &a, &b );
adj[a].push_back(b);
adj[b].push_back(a);
} memset( vis, false, sizeof(vis) );
//memset( fang, -1, sizeof(fang) );
//memset( path, 0, sizeof(path) ); int ans = dp( , , - );
printf( "%d\n", ans );
}
return ;
}