题意:
poj的良心中文题,不赘述了。
分析:
难点是想到能把题中的最优单连通子集问题转化为求树的最大权子树问题,之后我用的是孩子兄弟表示,当然在建树的时候直接dp也行。树的最大权子树感觉是最简单的树型dp了。
代码:
//poj 1192
//sep9
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int maxN=1024;
struct POINT{
int x,y,val,idx;
}p[maxN];
int n,e;
int son[maxN],bro[maxN],head[maxN],vis[maxN],dp[maxN];
struct EDGE
{
int v,next;
}edge[4*maxN];
int cmp(POINT a,POINT b)
{
return a.x==b.x?a.y<b.y:a.x<b.x;
}
void addedge(int x,int y)
{
edge[e].v=y;edge[e].next=head[x];head[x]=e++;
edge[e].v=x;edge[e].next=head[y];head[y]=e++;
}
void build_tree(int u){
vis[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(vis[v]==1) continue;
bro[v]=son[u];
son[u]=v;
build_tree(v);
}
}
void build()
{
memset(son,0,sizeof(son));
memset(bro,0,sizeof(bro));
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
e=0;
for(int i=1;i<=n;++i)
for(int j=1;j<i;++j)
if(abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y)==1)
addedge(i,j);
build_tree(1);
}
void dfs(int u)
{
int sum=0;
for(int v=son[u];v;v=bro[v]){
dfs(v);
if(dp[v]>0)
sum+=dp[v];
}
dp[u]=sum+p[u].val;
}
void solve()
{
memset(dp,0,sizeof(dp));
dfs(1);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].val);
build();
solve();
int ans=INT_MIN;
for(int i=1;i<=n;++i)
ans=max(ans,dp[i]);
printf("%d",ans);
return 0;
}