【poj1694】 An Old Stone Game

http://poj.org/problem?id=1694 (题目链接)

题意

  一棵树,现在往上面放石子。对于一个节点x,只有当它的直接儿子都放满石子时,才能将它直接儿子中的一个石子放置x上,并回收其它石子。问最少需要多少个石子才能将石子放到根节点上。

Solution

  显然,贪心。数据范围小的可怜,用f[x]表示将石子放到节点x需要的最小石子数。然后对于一个节点的儿子节点,先放f[x]大的,再放小的。

细节

  多组数据清空数组

代码

// poj1694
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#define LL long long
#define inf 2147483640
#define MOD 1000000007
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std;

const int maxn=1000;
struct edge {int to,next;}e[maxn];
int head[maxn],f[maxn],n,cnt;
vector<int> v[maxn];

bool cmp(int a,int b) {
	return a>b;
}
void link(int u,int v) {
	e[++cnt]=(edge){v,head[u]};head[u]=cnt;
	e[++cnt]=(edge){u,head[v]};head[v]=cnt;
}
void dfs(int x,int fa) {
	f[x]=1;
	for (int i=head[x];i;i=e[i].next) if (e[i].to!=fa) {
			dfs(e[i].to,x);
			v[x].push_back(f[e[i].to]);
		}
	sort(v[x].begin(),v[x].end(),cmp);
	for (int i=0;i<v[x].size();i++) f[x]=max(f[x],v[x][i]+i);
}
void Init() {
	for (int i=1;i<=n;i++) head[i]=0,v[i].clear();
	cnt=0;
}
int main() {
	int T;scanf("%d",&T);
	while (T--) {
		Init();
		scanf("%d",&n);
		for (int u,v,son,i=1;i<=n;i++) {
			scanf("%d%d",&u,&son);
			for (int j=1;j<=son;j++) {
				scanf("%d",&v);
				link(u,v);
			}
		}
		dfs(1,0);
		printf("%d\n",f[1]);
	}
	return 0;
}

  

posted @ 2016-12-25 17:00  MashiroSky  阅读(194)  评论(0编辑  收藏  举报