【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; }
This passage is made by MashiroSky.