哎,前幾天模擬考太多了,不是不想發部落格,是想法的太多了而又沒時間,還要訂題啊。。。
這幾天遇著兩道這樣的樹上兩兩匹配問題,就是互相稍微變一下型,但我一道都沒寫出來。
哎,真的感覺afo了,不過幸好的我目標不是省一。
不過有時候還是要做一些兩手準備。。。(\斜眼笑)
簡要題意:
給出一棵n點的樹,k個匹配點,求這k個點兩兩匹配的距離最小和。
\(solution:\)
一開始以為是什麼二分圖的帶權匹配啊啥的。
然後想了想複雜度,發現好像只能過第乙個subtest...
然後就自閉了。
結果正解就是這麼個鬼東西,思想特別巧妙,加上考了兩道,我決定寫一寫。
咳咳,不扯了。
因為我們顯然可以發現若是和子樹外的匹配會多出一堆沒什麼用的奇怪的代價。
這時候,你可以考慮每條邊的貢獻,因為只要把每條邊的貢獻加起來就是總距離和了。
對於每條邊,它的貢獻顯然是邊權乘子樹內無法完成匹配的點數。
因為對於匹配點,若是子樹內無法完成匹配,那一定要到子樹外去尋找的,這時候一定會經過此邊,所以直接累加這個貢獻即可。
以下的**是乙個實現兩種匹配點的dfs部分。0、2一類,1、3一類。
\(code:\)
void dfs(int u,int fa)
}
然後我們再考慮一題:
題意:給出一棵n點的無根樹,k個匹配點,求這k個點兩兩匹配的距離最大和。
\(solution\)
和上一題幾乎一樣,只需考慮改動哪些地方。
對於每條邊,因為子樹內盡量不匹配,但我們還需要考慮子樹外的問題,若子樹外的節點數比子樹內的少,這條邊最多被經過的次數不會超過子樹外的匹配點數。
所以我們最後遍歷一遍樹,累加子樹內的匹配點數,然後對於每條邊使最終答案加上\(min(si[v],k*2-si[v])\),其中si陣列是子樹內的匹配點數。
\(code:\)
void dfs(int u,int fa)
//這樣一遍dfs即可完成
ans+=min(si[u],m-si[u]);
}
emmmmm,就寫到這裡吧,這就乙個套路,學會,記住。 多點兩兩連線問題
問題描述 問題分解 當有兩個點時 只有1 2連線的情況 當有四個點時 會有1 2 3 4與1 4 2 3連線的情況,不能出現1 3這種交叉連線的情況 當有六個點時 問題分解到這裡,我們便能想到 這是乙個把複雜問題分解成子問題的需求,應用動態規劃即可,動態規劃的關鍵點在於找到子問題的解如何組合才能得到...
求樹上結點的兩兩距離和 DFS求解
對於一棵n個結點的樹,其n 1條邊有各自的邊權 長度 求樹上所有結點兩兩之間的距離和,即 i 1n 1 j i 1nd ista nce i,j sum sum distance i,j i 1 n 1 j i 1 n di stan ce i j 要求求一棵n個結點的樹上所有的任意兩點之間的距離和...
兩兩交換兩個相鄰節點
給定乙個鍊錶,兩兩交換其中相鄰的節點,並返回交換後的鍊錶。如 給定1 2 3 4,返回2 1 4 3。說明 方法一 交換兩個節點裡的值而節點不動。該題禁止這樣做 方法二 老老實實的交換就好了 我的 if head null return head if head.next null return h...