洛谷P2607 ZJOI2008 騎士 題解

2021-08-19 04:33:02 字數 1337 閱讀 4309

題目傳送門

題目大意:

每個騎士都有自己的戰鬥力且不能和另乙個特定的騎士同時出征,試問出征的騎士最大總戰鬥力是多少(總戰鬥力等於所有出征的騎士的戰鬥力之和)

思考過程:

做過洛谷p1352 沒有上司的舞會的同學肯定會覺得這個題和它很想,只不過那個題是n個點n-1條邊的樹,這個題是n個點n條邊的基環樹,多了乙個環而已。我們要思考怎麼轉化。我們首先找到環上的一條邊,斷開這條邊並記錄左右端點(假設為mark1,mark2),對左右端點分別做dp(dp和那個題一樣,沒做過那個題的同學可以先去做那個題),dp[i][0]表示在i的子樹中不取i的最大結果,dp[i][1]表示在i的子樹中取i的最大結果,那麼答案就是max(dp[mark1][0],dp[mark2][0])。為什麼這樣是對的呢?我們冷靜分析一下,mark1和mark2是不能同時選的,dp[mark1][0]表示不取mark1,mark2取不取就無所謂了,對於mark2同理,這樣我們就相當於完美的考慮了這條邊對答案的影響,正確性顯然。(注意可能有多個聯通塊,要把所有答案相加)

具體做法:

1.讀入時使用並查集找到環上的一條邊,記錄左右端點(mark1,mark2)

2.對左右端點分別做樹形dp(注意dp[mark1][0]和dp[mark2][0]是兩次dp分別得到的結果,並不是一次dp中得到的值)

3.將ans加上max(dp[mark1][0],dp[mark2][0]),繼續這個過程直到遍歷所有聯通塊

**:(注意此題樹形dp不能用bfs。我之前用的就是bfs,以為樹是乙個掃帚能卡過去,結果發現不可行qaq)

#include 

using

namespace

std;

const

int maxn=1e6+100;

struct stu

road[2*maxn]; int first[maxn],cnt=0;

long

long ans,dp[maxn][2],fa[maxn];

int n,val[maxn],mark1[maxn],mark2[maxn],cnt1=0;

void addedge(int x,int y)

int find(int x)

void dfs(int now)

}int main()

else

}for(int tt=1;tt<=cnt1;tt++)

printf("%lld\n",ans);

return

0;

}

洛谷 P2607 ZJOI2008 騎士

給出一幅有n個點,n條邊的無向未必聯通圖,每乙個點有乙個權並與另外乙個點相連,對其中一些點進行染色,且相鄰兩點的顏色不能都染,則最大的染色點權值和是多少.這題和 洛谷p1453城市環路 很像,區別就在於它不是連通圖.因而可以先用並查集和vector進行分塊,易證每一塊都是比樹多一條邊的連通圖,每一塊...

P2607 ZJOI2008 騎士(基環樹)

邊數等於點數,是基環樹。考慮dp,如果是樹的話,轉移方程為dp u 1 選擇u w u dp v 0 v為u的子節點 dp u 0 不選擇u max dp v 0 dp v 1 然後基環樹只要找到環後,斷開環上的一條邊就成了樹。斷開的邊上兩端點不能同時選擇,所以對於每棵基環樹,我們求兩邊dp,分別限...

洛谷P2607題解

想要深入學習樹形dp,我的部落格。本題的dp模型同 p1352 沒有上司的舞會。本題的難點在於如何把基環樹dp轉化為普通的樹上dp。考慮斷邊和換根。先找到其中的乙個環,在上面隨意取兩個點,斷開這兩個點的邊,使其變為一棵普通樹。以其中的一點為樹根做樹形dp,再以另一點為樹根再做一次樹形dp,因為相鄰的...