topcoder13185 TreePuzzle
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的更多相关文章
- TreePuzzle 一点感想
题目链接 这一道题看起来像是一道贪心的水题,但是情况较难考虑周全,比如下图,我就考虑漏了这种情况,点0是可以移动到点1的.然后我就各种奇怪的分类讨论.最终还是没能A,决定放弃治疗. 然后我看了看解答, ...
随机推荐
- PHP开发安全之近墨者浅谈(转)
==过滤输入/输出转义 过滤是Web应用安全的基础.它是你验证数据合法性的过程.通过在输入时确认对所有的数据进行过滤,你可以避免被污染(未过滤)数据在你的程序中被误信及误用.大多数流行的PHP应用的漏 ...
- xcode中的第三方库配置问题总结
xcode中的第三方库配置总结 在导入第三方库的时候,总是会遇到许多的问题.在这里,我记录一下学到的一些知识点.写得比较乱.只要是想要记录下来,在第三方库导入的时候,遇到的一些问题. 参考网址: ht ...
- WAMP 环境下,YII创建失败 提示 "'php.exe' 不是内部或外部命..."
现象: http://www.yiichina.com/guide/quickstart.first-app 使用这里的命令 % YiiRoot/framework/yiic webapp WebR ...
- Unix Shell 通配符、转义字符、元字符、特殊字符
shell通配符: * 匹配0或多个字符 a*b a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, a01b, ab等 ? 匹配任意一个字符 a?b a与b之间有且只有一个字符 ...
- Android Service生命周期及用法
Service概念及用途:Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行, ...
- VB 活动添加item元素
'ListView1.Columns.Clear() 'ListView1.Columns.Add("", 0, HorizontalAlignment.Center) 'List ...
- (转)PHP正则表达式的快速学习方法
1.入门简介 简单的说,正则表达式是一种可以用于模式匹配和替换的强有力的工具.我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影,例如,vi编辑器,Perl或PHP脚本语言,以及awk或 ...
- Android虚拟机GenyMotion
GenyMotion:需要VirtualBox,安装后可以选择机型,这个应该是Android for x86的一个改进版虚拟机,在原版的基础上针对不同机型用了和原机型同样的GUI,但是发现缺少了Goo ...
- Java序列化的机制和原理
Java序列化的机制和原理 本文讲解了Java序列化的机制和原理.从文中你可以了解如何序列化一个对象,什么时候需要序列化以及Java序列化的算法. 有关Java对象的序列化和反序列化也算是Java基础 ...
- Python sys.path.append
python sys.path.append 对于模块和自己写的程序不在同一个目录下,可以把模块的路径通过sys.path.append(路径)添加到程序中. 在程序开头加上: import syss ...