複雜樹形DP 題解
阿新 • • 發佈:2021-01-15
複雜樹形DP 題解
Analysis
- 幫助理解題意:左非法,走合法
- 情況(繞口令):
-
d
(
u
,
0
)
d(u,0)
- d ( u , 1 ) d(u,1) d(u,1): u u u不是伺服器, u u u的父親是伺服器, u u u的孩子不能是伺服器
- d ( u , 2 ) d(u,2) d(u,2): u u u不是伺服器且 u u u的父親不是伺服器, u u u的孩子必須有且僅有一個是伺服器
狀態轉移方程:
-
d
p
[
x
]
[
0
]
=
∑
m
i
n
(
d
p
[
v
]
[
0
]
,
d
p
[
v
]
[
1
]
)
+
1
,
v
∈
s
o
n
s
dp[x][0]=\sum min(dp[v][0],dp[v][1])+1,v \in sons
- d p [ x ] [ 1 ] = ∑ d p [ v ] [ 2 ] , v ∈ s o n s dp[x][1]=\sum dp[v][2],v \in sons dp[x][1]=∑dp[v][2],v∈sons
-
d
p
[
x
]
[
2
]
=
m
i
n
(
d
p
[
x
]
[
2
]
,
d
p
[
v
]
[
0
]
+
∑
d
p
[
V
i
]
[
2
]
)
dp[x][2]=min(dp[x][2],dp[v][0]+\sum dp[Vi][2])
dp[x][2]=min(dp[x][2]
優化狂魔: d p [ x ] [ 2 ] = m i n ( d p [ x ] [ 2 ] , d p [ x ] [ 1 ] − d [ v ] [ 2 ] + d [ v ] [ 0 ] ) , v ∈ s o n s dp[x][2]=min(dp[x][2],dp[x][1]-d[v][2]+d[v][0]),v \in sons dp[x][2]=min(dp[x][2],dp[x][1]−d[v][2]+d[v][0]),v∈sons
CODE
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int NR=1e4+5;
const int MR=1e5+5;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
int n,u,v,op;
struct Edge
{
int v,nxt;
}g[NR<<1];
int fte[NR],gsz;
void adde(int u,int v)
{
g[++gsz]=(Edge){v,fte[u]};
fte[u]=gsz;
}
int dp[NR][3];
void dfs(int x,int fa)
{
dp[x][0]=1;
dp[x][2]=NR;
for(int i=fte[x];i;i=g[i].nxt)
{
int y=g[i].v;
if(y==fa)
continue;
dfs(y,x);
dp[x][0]+=min(dp[y][1],dp[y][0]);
dp[x][1]+=dp[y][2];
}
for(int i=fte[x];i;i=g[i].nxt)
{
int y=g[i].v;
if(y==fa)
continue;
dp[x][2]=min(dp[x][2],dp[y][0]+dp[x][1]-dp[y][2]);
}
}
void solve()
{
memset(fte,0,sizeof(fte));
memset(dp,0,sizeof(dp));
gsz=0;
scanf("%d",&n);
for(int i=1;i<n;++i)
{
scanf("%d%d",&u,&v);
adde(u,v);
adde(v,u);
}
dfs(1,1);
printf("%d\n",min(dp[1][2],dp[1][0]));
}
int main()
{
while(1)
{
solve();
scanf("%d",&op);
if(op==-1)
break;
}
return 0;
}