您的位置:首页 > 其它

【luogu3621】【APIO2007】风铃(树形DP)

2017-10-18 09:39 453 查看

题目描述:

风铃传送门

算法:

树形DP

做法:

首先说明,我的做法比较麻烦,但思路是很清晰的。

1. 看看是否满足条件一

用一个 dfs 求出所有结点的深度,并看看满不满足条件一

2. 看看有没有解

dfs 一遍,对每一个结点 u 求一个 h[u],其中

h[u]=1 表示 u 子树内的所有风铃都是最深的

h[u]=2 表示 u 子树内的所有风铃都是最浅的

h[u]=3 表示 u 子树内的风铃有深有浅

设 v1 和 v2 分别为 u 的两个孩子,若 h[v1]=3并且h[v2]=3,那么无解。

3. 求解

dfs 一遍,满足

(h[u的左孩子]!=1并且h[u的右孩子]==1)或者(h[u的左孩子]==2并且h[u的右孩子]==3)

就需要交换一次。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=100010;
int n, mi;
int f
[2];

int Md, ans, M;             // M:风铃的最大深度-1  Md:第一个遇见的风铃深度-1
int dep
, h
;           // h[u]=1 表示 u 子树内的所有风铃都是最深的
// h[u]=2 表示 u 子树内的所有风铃都是最浅的
// h[u]=3 表示 u 子树内的风铃有深有浅

bool dfs1(int u){           // 检验是否满足条件 1
if(f[u][0]!=-1){
dep[f[u][0]] = dep[u]+1;
if(!dfs1(f[u][0])) return false;
}else{
M = max(M, dep[u]);
if(Md==0) Md = dep[u];
else if(dep[u]-Md>1 || dep[u]-Md<-1) return false;
}
if(f[u][1]!=-1){
dep[f[u][1]] = dep[u]+1;
if(!dfs1(f[u][1])) return false;
}else{
M = max(M, dep[u]);
if(Md==0) Md = dep[u];
else if(dep[u]-Md>1 || dep[u]-Md<-1) return false;
}
return true;
}

bool dfs2(int u){           // 检验是否有解
if(f[u][0]!=-1){ if(!dfs2(f[u][0])) return false; h[u] = h[f[u][0]]; }
else h[u] = (dep[u]==M ? 1 : 2);

if(f[u][1]!=-1){
int v = f[u][1];
if(!dfs2(v)) return false;
if(h[u]==3 && h[v]==3) return false;
if(h[v]==3 || (h[u]==2 && h[v]==1) || (h[u]==1 && h[v]==2)) h[u]=3;
}else{
if(dep[u]==M){
if(h[u]!=1) h[u]=3;
}
else if(h[u]!=2) h[u]=3;
}

return true;
}

void dfs3(int u){           // 计算答案
int v;
if(f[u][0]!=-1 && f[u][1]!=-1){ dfs3(f[u][0]); dfs3(f[u][1]); }
if((h[f[u][0]]!=1 && h[f[u][1]]==1) || (h[f[u][0]]==2 && h[f[u][1]]==3)) ans++;
}

int main(){
scanf("%d",&n);
for(int i=1, a1, a2; i<=n; ++i){
scanf("%d%d", &a1, &a2);
f[i][0] = a1; f[i][1] = a2;     // 因为是二叉树,且每一个点的左右孩子都已确定,就不用邻接表了
}
dep[1] = 1;
if(!dfs1(1)){ puts("-1"); return 0; }
if(!dfs2(1)){ puts("-1"); return 0; }
dfs3(1);
printf("%d\n",ans);
while(1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp dfs 算法