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. centos 6+安装山逗斯骚尅特(本文内容来自都比更具帝)

    系统支持:CentOS 6+,Debian 7+,Ubuntu 12+ 内存要求:≥128M 关于本脚本 一键安装 Shadowsocks-Python, ShadowsocksR, Shadowso ...

  2. 【转】iOS中流(Stream)的使用

    转自:http://southpeak.github.io/blog/2014/07/17/ioszhong-liu-stream-de-shi-yong/流提供了一种简单的方式在不同和介质中交换数据 ...

  3. jquery Tab默认情况下自动切换

    <!DOCTYPE html><html lang="zh-CN"><head><meta http-equiv="Conten ...

  4. Volley框架使用(POST)

    需要在MyApplication(继承Application)中配置; public static RequestQueue requestQueue; @Override public void o ...

  5. Android开发手记(15) 拨打电话和收发短信

    1.Intent简介 Android组价之间的通信,由Intent来协助完成.Intent负责对应用中一次操作的动作.动作涉及数据.附加数据进行描述,Android则根据此Intent的描述,负责找到 ...

  6. mac在 aliyun linux ecs实例上安装 jdk tomcat mysql

    用了一个ftp 工具 把 gz rpm 等 传递到ecs 上 -- 用这个Transmit 用ssh远程登录,然后依次安装 jdk tomcat  mysql 到 /usr/local/... 设置环 ...

  7. Cacti添加threshold、monitor和setting

    Cacti版本:Version 0.8.8b 一.插件介绍: monitor:通过简单明了的图标提供服务器的运行状态 settings:给不同的插件提供一些共用的信息,如邮件信息,dns信息thold ...

  8. 使用PPRevealSideViewController实现侧滑效果

    使用起来还是比较简单的, 主要是几个步骤 AppDelegate.m - (BOOL)application:(UIApplication *)application didFinishLaunchi ...

  9. 三、C# 运算符和控制流

    通常运算符划分为3大类: 一元运算符.二元运算会.三元运算符,它们对应的操作数分别是1个.2个.3 个. 结合性和优先级顺序. 二元运算会是从左向右结合的,相反赋值运算符是从右向左结合的.   cha ...

  10. C# 深入浅出 委托与事件

    C#中的委托和事件的概念接触很久了,但是一直以来总没有特别透彻的感觉,现在我在这里总结一下: 首先我们要知道委托的由来,为什么要使用委托了? 我们先看一个例子: 假设我们有这样一个需求,需要计算在不同 ...