https://community.topcoder.com/stat?c=problem_statement&pm=13185

被wck屠了。

考试时候想分类讨论,结果发现情况有点复杂,最后还是没调出来。

回去看了看题解,发现好像是树形DP,状态记得很巧妙。

假设当前红点在$x$,从$fa$来,容易知道此时$fa$是空的。

容易知道以$fa$为根的子树(即如图的绿色圈)中的黑点是可以任意移动的。

因为$fa$是空的,所以我们可以先把红点从$x$移到$fa$,然后将以$x$为子树中的所以黑点任意移动,最后再把红点从$fa$移到$x$。

所以以$x$为根的子树(即如图的蓝色圈)中的黑点也是可以任意移动的。

所以我们只需要知道以$x$为根的子树中的黑点的个数即可。

记$vis[x][fa][c]$表示当前红点在$x$,从$fa$来,且以$x$为根的子树中的黑点的个数为$c$的状态,$1$表示可以到达这种状态,$0$表示不可以到达这种状态。

然后DP即可。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b) for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} inline int sgn(DB x){if(abs(x)<1e-)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxn=; int n;
int d[maxn+],g[maxn+][maxn+];
int mark[maxn+];
int sz[maxn+][maxn+];//sz[i][j]表示i的父亲为j时,子树i的大小
int bl[maxn+];
int res[maxn+]; void addedge(int u,int v){g[u][++d[u]]=v;} int calsz(int x,int fa)
{
int &res=sz[x][fa],j;
if(res)return res;
res=;
re(j,,d[x])if(g[x][j]!=fa)res+=calsz(g[x][j],x);
return res;
}
int calbl(int x,int fa)
{
int &res=bl[x],j;
res=mark[x];
re(j,,d[x])if(g[x][j]!=fa)res+=calbl(g[x][j],x);
return res;
} queue<int>Q;
int vis[maxn+][maxn+][maxn+];
void push(int x,int fa,int c)
{
if(vis[x][fa][c])return;
vis[x][fa][c]=;
Q.push((x<<)|(fa<<)|c);
} int main()
{
freopen("puzzle.in","r",stdin);
freopen("puzzle.out","w",stdout);
int i,j;
n=gint();
re(i,,n){int fa=gint()+;if(fa)addedge(fa,i),addedge(i,fa);}
re(i,,n)re(j,,d[i])calsz(i,g[i][j]);
re(i,,n)mark[i]=gint();mark[]=;
calbl(,-);
int total=bl[];
re(j,,d[])
{
int v=g[][j];
if(sz[v][]>bl[v])push(v,,bl[v]);
}
res[]=;
while(!Q.empty())
{
int status=Q.front(),x=status>>,fa=(status>>)&,c=status&;Q.pop();//当前红点在x,从fa来,子树内的黑点数为c
res[x]=;
if(total-c<sz[fa][x])push(fa,x,total-c);
int sc=;
re(j,,d[x])if(g[x][j]!=fa)sc+=sz[g[x][j]][x];
re(j,,d[x])if(g[x][j]!=fa)
{
int v=g[x][j];
for(int c2=;c2<=c && c2<sz[v][x];c2++)if(c-c2<=sc-sz[v][x])push(v,x,c2);
}
}
re(i,,n)PF("%d ",res[i]);PF("\n");
return ;
}

topcoder13185 TreePuzzle的更多相关文章

  1. TreePuzzle 一点感想

    题目链接 这一道题看起来像是一道贪心的水题,但是情况较难考虑周全,比如下图,我就考虑漏了这种情况,点0是可以移动到点1的.然后我就各种奇怪的分类讨论.最终还是没能A,决定放弃治疗. 然后我看了看解答, ...

随机推荐

  1. Reso | liunx下longeneQQ和搜狗拼音

    sogoupinyin_2.0.0.0078_amd64.deb:   http://pan.baidu.com/s/1eSDLvEU WineQQ7.8-20151109-Longene .deb: ...

  2. HTTP in iOS你看我就够

    HTTP属于老话题了,在项目中我们经常需要往服务端发POST或者GET请求,但是对于HTTP的了解不应只局限于此.千里之行,始于足下.越想走的远,基本原理就应该了解的透彻全面一些,仅仅停留在使用ASI ...

  3. 鼠标双击范围基于Win7

    TP鼠标双击范围主要是修改Registry中的HKEY_CURRENT_USER\Control Panel\Mouse里面的两个参数 DoubleClickHeight跟DoubleClickWid ...

  4. KMP和扩展KMP【转】

    这种东西基本上在纸上自己推导一下就能做出来XD 转发注明出处 KMP 给出两个字符串A(称为模板串)和B(称为子串),长度分别为lenA和lenB,要求在线性时间内,对于每个A[i] (0<=i ...

  5. .NET六大剑客:栈、堆、值类型、引用类型、装箱和拆箱

    .NET六大剑客:栈.堆.值类型.引用类型.装箱和拆箱 一.“堆”,“栈”专区 这两个字我相信大家太熟悉了,甚至于米饭是什么?不知道...“堆”,“栈”是什么?哦,这个知道... 之前我也写过一篇堆栈 ...

  6. public static <T> Map<String, T> json2map

    /** * json string convert to map with javaBean */ public static <T> Map<String, T> json2 ...

  7. 学习日记_SSH框架web.xml配置文件篇

    1.参考一:http://www.blogjava.net/yxhxj2006/archive/2012/07/09/382632.html 2.参考二: <!-- web 容器启动spring ...

  8. <blockquote>标签,长文本引用

    <blockquote>的作用也是引用别人的文本.但它是对长文本的引用,如在文章中引入大段某知名作家的文字,这时需要这个标签. 等等,上一节<q>标签不是也是对文本的引用吗?不 ...

  9. Swift - 33 - 返回函数类型和函数嵌套

    //: Playground - noun: a place where people can play import UIKit /*---------------------------返回函数类 ...

  10. 05DotNet基本常用类库

    1.String成员方法(常用) bool Contains(String str);判断字符串对象是否包含给定的字符串; bool StartsWith(String str);判断字符串对象是否以 ...