BalticOI2021 The Xana coup(切換)
阿新 • • 發佈:2022-05-23
The Xana coup(切換)BalticOI2021 loj3563
非常顯然,這題一眼望過去就知道是樹形dp,也不難想到令\(dp[x][i][j](i=0/1,j=0/1)\)表示以x為根的子樹(除了x)都變成了0,x為i(對於當前要更新的x,i是沒更新的,對於已經更新過的,i是更新過的),若j為0,則沒有點x,若j為1,則點了一下x。(這裡點了x指,對x進行切換操作)
void dfs(int x,int fa) { dp[x][a[x]^1][0]=dp[x][a[x]^1][1]=inf; for(int i=head[x];i;i=edge[i].nxt) { int y=edge[i].to; if(y==fa) continue; dfs(y,x); int a=min(dp[x][0][0]+dp[y][0][0],min(dp[x][1][0]+dp[y][0][1],inf)); int b=min(dp[x][1][0]+dp[y][0][0],min(dp[x][0][0]+dp[y][0][1],inf)); int c=min(dp[x][0][1]+dp[y][1][0],min(dp[x][1][1]+dp[y][1][1],inf)); int d=min(dp[x][1][1]+dp[y][1][0],min(dp[x][0][1]+dp[y][1][1],inf)); dp[x][0][0]=a; dp[x][1][0]=b; dp[x][0][1]=c; dp[x][1][1]=d; } int a=min(dp[x][0][1]+1,inf); int b=min(dp[x][1][1]+1,inf); dp[x][1][1]=a;dp[x][0][1]=b; }
顯然答案就是 \(min(dp[1][0][0],dp[1][0][1])\)
不得不說 這個樹形dp轉移的時候特別妙妙。為了防止更新答案後又要用更新前的答案,可以先記錄答案,放到所有答案更新完後再更新
反思:這種結論一看就對的題 應該通過小樣例調錯