ACM 285. [NOI1999] 最優連通子集(DFS)

285. [NOI1999] 最優連通子集

★☆   輸入文件:subset.in   輸出文件:subset.out   簡單對比
時間限制:1 s   內存限制:128 MB

衆所周知,我們可以通過直角座標系把平面上的任何一個點P用一個有序數對(x,y)來唯一表示,如果x,y都是整數,我們就把點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;< li="">
  • 我們則稱點R與點T在整點集S上連通,把點序列Q1,Q2,…,Qk稱爲整點集S中連接點R與點T的一條道路。

定義4

  • 若整點集V滿足:對於V中的任何兩個整點,V中有且僅有一條連接這兩點的道路,則V稱爲單整點集。

定義5

  • 對於平面上的每一個整點,我們可以賦予它一個整數,作爲該點的權,於是我們把一個整點集中所有點的權的總和稱爲該整點集的權和。

我們希望對於給定的一個單整點集V,求出一個V的最優連通子集B,滿足:

  1. B是V的子集
  2. 對於B中的任何兩個整點,在B中連通;
  3. B是滿足條件(1)和(2)的所有整點集中權和最大的。

輸入

第1行是一個整數N,表示單整點集V中點的個數;

以下N行中,第i行(1<=i<=N)有三個整數,Xi,Yi,Ci依次表示第i個點的橫座標,縱座標和權。同一行相鄰兩數之間用一個空格分隔。

輸出

僅一個整數,表示所求最優連通集的權和。

樣例輸入

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

樣例輸出

2

參數約定

  • 2<=N<=1000
  • -10^6<=Xi,Yi<=10^6
  • -100<=Ci<=100
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

#define INF 9999999
#define MAX_N 1000

struct Node
{
	int x,y;
	int v;
	int deg;
	int link[4];
} sset[MAX_N];
int n;
bool vis[MAX_N];
int val[MAX_N];

bool IsLink(const Node &a,const Node &b)
{
	if(abs(a.x-b.x)+abs(a.y-b.y)==1)
	{
		return true;
	}

	return false;
}

int dfs(int v)
{
	if(vis[v]) return val[v];
	vis[v]=true;

	int sum=0;
	for(int i=0;i<sset[v].deg;i++)
		sum+=max(0,dfs(sset[v].link[i]));

	sum=max(0,sum+sset[v].v);

	return val[v]=sum;
}

int main()
{
	freopen("subset.in","r",stdin);
	freopen("subset.out","w",stdout);

	scanf("%d",&n);

	for(int i=0;i<n;i++)
	{
		scanf("%d%d%d",&sset[i].x,&sset[i].y,&sset[i].v);

		for(int j=0;j<i;j++)
		{
			if(IsLink(sset[i],sset[j]))
			{
				   sset[i].link[sset[i].deg++]=j;
				   sset[j].link[sset[j].deg++]=i;
			}
		}
	}

	dfs(0);
	int maxx;
	maxx=-INF;

	for(int i=0;i<n;i++)
	{
		maxx=max(maxx,val[i]);
	}

	printf("%d\n",maxx);

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章