您的位置:首页 > 其它

hdu 1054 #树形DP

2012-07-18 19:44 330 查看
在一棵树上求最小顶点覆盖,树形dp

dp[i][0] 表示不选结点i

dp[i][1]表示选择结点i

dp[i][0] = sum(dp[i_sons][1])

dp[i][1] = sum( min( dp[i_sons][0], dp[i_sons][1] )

先建双向图,然后处理成结点从上到下的树

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define NN 1600
#define N 3100
#define INF 1<<30

int mat[NN][NN];
int pnt
,nxt
,head
;
int dp
[2];
int e;
void addEdge(int u,int v)
{
pnt[e] = v;
nxt[e] = head[u];
head[u] = e++;
}
void cle(int u)
{
for(int i = head[u]; i != -1; i = nxt[i])
{
int v = pnt[i];
if(mat[u][v])
{
mat[v][u] = 0;
cle(v);
}

}
}
int dfs(int id,int sel)
{
if(dp[id][sel] != INF)
return dp[id][sel];

int sum = sel;
int i,u;
for(i = head[id]; i != -1; i = nxt[i])
{

u = pnt[i];
if(!mat[id][u])
continue;
if(sel == 0)
sum += dfs(u,1);
else
sum += min(dfs(u,1),dfs(u,0));
}
return dp[id][sel] = sum;
}
int main()
{
int n,i,u,v,m;
while(scanf("%d",&n) == 1 )
{
e = 0;
memset(head,-1,sizeof(head));
memset(mat,0,sizeof(mat));
for(i = 0; i < n; ++i)
{
scanf("%d:(%d)",&u,&m);
while(m--)
{
scanf("%d",&v);
mat[u][v] = mat[v][u] = 1;
addEdge(u,v);
addEdge(v,u);
}
}
cle(0);
for(i = 0; i < n; ++i)
dp[i][0] = dp[i][1] = INF;
printf("%d\n",min(dfs(0,1),dfs(0,0)));
}
return 0;
}
/*
3
0:(2) 1 2
1:(0)
2:(0)
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: