BZOJ 1149 风铃(树形DP)
题目描述的实际是一颗二叉树,对于每个结点,要么满叉,要么无叉。
对于一种无解的简单情况,我们搜一遍树找到最浅的叶子结点1和最深的叶子结点2,如果dep[1]<dep[2]-1,则显然无解。
所以现在所有的叶子结点的深度要么是dep[1]和dep[2].
我们可以把所有结点用node[x]标记状态。
node[x]=0表示x的子树下所有叶子结点深度都是dep[2]。
node[x]=1表示x的子树下一部分叶子结点深度是dep[1],一部分是dep[2]。
node[x]=2表示x的子树下所有叶子结点深度都是dep[1]。
现在有,假设x的儿子结点的node值都是1,则一定无解。证明是显然的。
假设x的左儿子结点node值大于右儿子结点的node值,则ans+1,表示需要操作一次。证明也是显然的。
另外node值可以通过一次树形DP得到,所以总复杂度为O(n).
# include <cstdio> # include <cstring> # include <cstdlib> # include <iostream> # include <vector> # include <queue> # include <stack> # include <map> # include <set> # include <cmath> # include <algorithm> using namespace std; # define lowbit(x) ((x)&(-x)) # define pi acos(-1.0) # define eps 1e-8 # define MOD 1000000007 # define INF 1000000000 # define mem(a,b) memset(a,b,sizeof(a)) # define FOR(i,a,n) for(int i=a; i<=n; ++i) # define FO(i,a,n) for(int i=a; i<n; ++i) # define bug puts("H"); # define lch p<<1,l,mid # define rch p<<1|1,mid+1,r # define mp make_pair # define pb push_back typedef pair<int,int> PII; typedef vector<int> VI; # pragma comment(linker, "/STACK:1024000000,1024000000") typedef long long LL; int Scan() { int res=0, flag=0; char ch; if((ch=getchar())=='-') flag=1; else if(ch>='0'&&ch<='9') res=ch-'0'; while((ch=getchar())>='0'&&ch<='9') res=res*10+(ch-'0'); return flag?-res:res; } void Out(int a) { if(a<0) {putchar('-'); a=-a;} if(a>=10) Out(a/10); putchar(a%10+'0'); } const int N=100005; //Code begin... int pos, mi=INF, ma=0, node[N*10], dep[N*10], n, ans, son[N][2]; void dfs1(int x) { if (x>n) mi=min(mi,dep[x]), ma=max(ma,dep[x]); else { dep[son[x][0]]=dep[son[x][1]]=dep[x]+1; dfs1(son[x][0]), dfs1(son[x][1]); } } bool dfs2(int x) { if (x>n) { if (dep[x]<ma) node[x]=2; else node[x]=0; } else { if (dfs2(son[x][0])==0 || dfs2(son[x][1])==0) return 0; if(node[son[x][0]]==1&&node[son[x][1]]==1) return 0; else if (node[son[x][0]]==2&&node[son[x][1]]==2) node[x]=2; else if (node[son[x][0]]==0&&node[son[x][1]]==0) node[x]=0; else { if (node[son[x][0]]>node[son[x][1]]) ++ans; node[x]=1; } } return 1; } int main () { int u, v; scanf("%d",&n); pos=n; FOR(i,1,n) { scanf("%d%d",&u,&v); if (u==-1) u=++pos; if (v==-1) v=++pos; son[i][0]=u, son[i][1]=v; } dfs1(1); if (mi<ma-1||dfs2(1)==0) puts("-1"); else printf("%d\n",ans); return 0; }