1. 程式人生 > 實用技巧 >Gym102460B The Power Monitor System(樹形dp)

Gym102460B The Power Monitor System(樹形dp)

當不存在沒有被染色的邊時: 若被自己染黑,則由於規則 1,這個點染了以後所有兒子都會被染 色,因此兒子的情況可以隨便選:

fu,1,0 = 1 + ∑min{fv,0/1/2,0/1}

若被兒子染黑,則必須要選擇一個兒子傳遞上去,兒子能傳遞上 來只有兩種情況: fu,0,0 = minv{min{fv,0,0, fv,1,0} + ∑ v ′̸=v min{fv,0,0, fv,0,1, fv,1,0}}

若只被父親染黑,則兒子不能把 u 染黑,為了 u 和兒子之間的邊 能夠被覆蓋,只能用規則 2,發現只有一種情況:fu,2,0 = ∑fv,0,1

當與兒子的邊中存在一條沒有被染色時: 若被兒子染黑,那麼要在上面的 fu,0,0 中轉移式的 v ′ 中再抽出一 個 v ′′,這個 v ′′ 的貢獻只能是 min{fv ′′ ,2,0/1}

若只被父親染黑,同理,在上面的 fu,2,0 中轉移式的 v 中抽出一個 v ′,這個 v ′ 的貢獻也只能是 min{fv ′ ,2,0/1}

時間複雜度 O(n)。

存在一條沒有被染色的提取出來的代價的意義是,我們定義的狀態f[u][2][1]是u與兒子在一條邊沒被染色,這條邊因為規則4,其他邊都被染色的情況下染色的狀態,因此我們需要提取出這個資訊。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e5+10;
const int inf=0x3f3f3f3f;
ll f[N][
3][3]; int h[N],ne[N],e[N],idx; int in[N]; void add(int a,int b){ e[idx]=b,ne[idx]=h[a],h[a]=idx++; } void dfs(int u,int fa){ f[u][1][0]=1,f[u][2][0]=0; if(in[u]==1&&fa!=-1) return ; f[u][0][0]=f[u][0][1]=f[u][2][0]=f[u][2][1]=0; ll g[2]={0,inf}; ll tmp[2][2]={0,inf,inf,inf};
for(int i=h[u];i!=-1;i=ne[i]){ int v=e[i]; if(v==fa) continue; dfs(v,u); ll tmp1=min(f[v][1][0],min(f[v][0][1],f[v][0][0])); g[1]=min(g[1]+tmp1,g[0]+min(f[v][1][0],f[v][0][0])); g[0]+=tmp1; tmp[1][1]=min(tmp[1][1]+tmp1,min(tmp[0][1]+min(f[v][1][0],f[v][0][0]),tmp[1][0]+min(f[v][2][1],f[v][2][0]))); tmp[1][0]=min(tmp[1][0]+tmp1,tmp[0][0]+min(f[v][1][0],f[v][0][0])); tmp[0][1]=min(tmp[0][1]+tmp1,tmp[0][0]+min(f[v][2][1],f[v][2][0])); tmp[0][0]+=tmp1; f[u][1][0]+=min(f[v][1][0],min(f[v][0][0],min(f[v][0][1],min(f[v][2][0],f[v][2][1])))); f[u][2][1]=min(f[u][2][0]+min(f[v][2][1],f[v][2][0]),f[u][2][1]+f[v][0][1]); f[u][2][0]+=f[v][0][1]; } f[u][0][0]=g[1]; f[u][0][1]=tmp[1][1]; } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int n; cin>>n; for(int i=1;i<=n;i++){ for(int j=0;j<3;j++){ for(int k=0;k<2;k++) f[i][j][k]=0x3f3f3f3f; } } for(int i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b); add(b,a); in[a]++; in[b]++; } dfs(1,-1); cout<<min(f[1][1][0],min(f[1][0][0],f[1][0][1]))<<endl; }
View Code