最優(yōu)連通子集
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 1649   Accepted: 855

Description

眾所周知,我們可以通過直角坐標系把平面上的任何一個點P用一個有序數(shù)對(x, y)來唯一表示,如果x, y都是整數(shù),我們就把點P稱為整點,否則點P稱為非整點。我們把平面上所有整點構成的集合記為W。
定義1 兩個整點P1(x1, y1), P2(x2, y2),若|x1-x2| + |y1-y2| = 1,則稱P1, P2相鄰,記作P1~P2,否則稱P1, P2不相鄰。
定義 2 設點集S是W的一個有限子集,即S = {P1, P2,..., Pn}(n >= 1),其中Pi(1 <= i <= n)屬于W,我們把S稱為整點集。
定義 3 設S是一個整點集,若點R, T屬于S,且存在一個有限的點序列Q1, Q2, ?, Qk滿足:
1. Qi屬于S(1 <= i <= k);
2. Q1 = R, Qk = T;
3. Qi~Qi + 1(1 <= i <= k-1),即Qi與Qi + 1相鄰;
4. 對于任何1 <= i < j <= k有Qi ≠ Qj;
我們則稱點R與點T在整點集S上連通,把點序列Q1, Q2,..., Qk稱為整點集S中連接點R與點T的一條道路。
定義4 若整點集V滿足:對于V中的任何兩個整點,V中有且僅有一條連接這兩點的道路,則V稱為單整點集。
定義5 對于平面上的每一個整點,我們可以賦予它一個整數(shù),作為該點的權,于是我們把一個整點集中所有點的權的總和稱為該整點集的權和。
我們希望對于給定的一個單整點集V,求出一個V的最優(yōu)連通子集B,滿足:
1. B是V的子集
2. 對于B中的任何兩個整點,在B中連通;
3. B是滿足條件(1)和(2)的所有整點集中權和最大的。

Input

第1行是一個整數(shù)N(2 <= N <= 1000),表示單整點集V中點的個數(shù);
以下N行中,第i行(1 <= i <= N)有三個整數(shù),Xi, Yi, Ci依次表示第i個點的橫坐標,縱坐標和權。同一行相鄰兩數(shù)之間用一個空格分隔。-10^6 <= Xi, Yi <= 10^6;-100 <= Ci <= 100。

Output

僅一個整數(shù),表示所求最優(yōu)連通集的權和。

Sample Input

5
0 0 -2
0 1 1
1 0 1
0 -1 1
-1 0 1

Sample Output

2

Source

 
 
/*********************************************
POJ1192最優(yōu)連通子集
題目意思:如果兩個點的距離相差一,則兩個點相鄰或著說連通。
求:連通圖的最大加權和。

思路:對給出的 n 個點建樹,然后就是灰常簡單的樹形DP了。

f[ p ] 表示節(jié)點 p 含有的最大值,最后用個for循環(huán)遍歷各個節(jié)點找出最大加權和。


*********************************************
*/
#include<iostream>
#include<stdio.h>
#include<vector>
#include<math.h>
using namespace std;
const int MAXN=1005;
int n;
bool used[MAXN];
int f[MAXN];
struct Node
{
int x,y,v;
}tt[MAXN];
vector<int>child[MAXN];
bool near(int p,int q)//判斷兩個整點是否相鄰
{
if(fabs((double)tt[p].x-tt[q].x)+fabs((double)tt[p].y-tt[q].y)==1)return true;
return false;
}
void dfs(int p)
{
used[p]=true;
for(int i=1;i<=n;i++)
{
if(!used[i]&&near(p,i))
{
child[p].push_back(i);
dfs(i);
}
}
}
void recur(int p)
{
if(child[p].size()==0)
{
f[p]=tt[p].v;
return;
}
for(int i=0;i<child[p].size();i++)
recur(child[p][i]);
f[p]=tt[p].v;
for(int i=0;i<child[p].size();i++)
if(f[child[p][i]]>0)f[p]+=f[child[p][i]];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d%d",&tt[i].x,&tt[i].y,&tt[i].v);
for(int i=1;i<=n;i++) child[i].clear();
memset(used,false,sizeof(used));
dfs(1);
recur(1);
int ans=0;
//for(int i=1;i<=n;i++)
//if(f[i]>ans)ans=f[i];
printf("%d\n",f[1]);
system("pause");
return 0;
}

文章來源:http://www.cnblogs.com/kuangbin/archive/2011/11/13/2247173.html