題目描述
小l 最近沉迷於塞爾達傳說:荒野之息(the legend of zelda: breath of the wild)無法自拔,他尤其喜歡遊戲中的迷你挑戰。
遊戲中有乙個叫做「lct」 的挑戰,它的規則是這樣子的:現在有乙個n 個點的 樹(tree),每條邊有乙個整數邊權vi ,若vi >= 0,表示走這條邊會獲得vi 的收益;若vi < 0 ,則表示走這條邊需要支付- vi 的過路費。小l 需要控制主角link 切掉(cut)樹上的 恰好k 條邊,然後再連線 k 條邊權為 0 的邊,得到一棵新的樹。接著,他會選擇樹上的兩個點p; q ,並沿著樹上連線這兩點的簡單路徑從p 走到q ,並為經過的每條邊支付過路費/ 獲取相應收益。
海拉魯大陸之神temporarydo 想考驗一下link。他告訴link,如果link 能切掉 合適的邊、選擇合適的路徑從而使 總收益 - 總過路費最大化的話,就把傳說中的大師之劍送給他。
小 l 想得到大師之劍,於是他找到了你來幫忙,請你告訴他,link 能得到的 總收益 - 總過路費最大是多少。
題解
先考慮斷掉k條邊又連上k條邊這個問題,因為最後我們只需要選取最終的樹上的一條鏈,所以我們連上這k條邊相當於是把這條鏈分成k+1段。
所以我們需要找到樹上相互無交的嚴格的k+1條鏈(根據題目描述,乙個點也可以算做一條鏈)。
為什麼要嚴格k+1段呢?因為這k+1段之間不能有交,所以必然會空出k條沒有被選的邊,正好可以留給我們斷邊用。
好了,題目大概分析要這裡,然後dp鏈的問題有乙個經典做法就是揹包,因為不能有交,所以每個點只可能有三種狀態012,表示這個點向下的邊中有幾條被選了,dp時討論一下。
#include#includeview code#include
#define n 300002
#define m 103
using
namespace
std;
typedef
long
long
ll;ll dp[n][m][3];
inttot,head[n],n,k;
inline ll rd()
while(isdigit(c))
return f?-x:x;
} struct edgee[n<<1
];inline
void add(int u,int v,ll l)
inline ll mx(ll x,ll y,ll z)
void dfs(int u,int
fa) }
}}int
main()
dfs(
1,0);
cout
<1][k+1][2],max(dp[1][k+1][0],dp[1][k+1][1
]));
return0;
}
因為有負邊權的存在,隨著k的增加,答案不一定是嚴格單調遞增的。
但是我們可以發現,答案是乙個上凸函式 。
解決這種問題一般的操作是帶權二分。
在這道題中,我們二分乙個權mid,代表每選擇一條鏈都要付出-mid的代價。
然後按照上面的方法直接按照權值大小貪心的做o(n)的dp。
然後看看最優解選沒選夠k+1條鏈,夠了就加大mid,否則減小mid。
#include#includeview code#include
#include
#define n 300002
#define m 103
#define inf 1e18
using
namespace
std;
typedef
long
long
ll;int
tot,head[n],n,k;
ll sum,mid,ans;
inline ll rd()
while(isdigit(c))
return f?-x:x;
} struct edgee[n<<1
];inline
void add(int u,int v,ll l)
struct
node
node
operator +(const node &b)const
; }
node
operator +(const ll &b)const
; }
}dp[n][3];
void dfs(int u,int
fa);dp[u][0]=node;dp[u][1]=node;
for(int i=head[u];i;i=e[i].n)if(e[i].to!=fa));
dp[u][
1]=max(dp[u][1]+dp[v][0],dp[u][0]+dp[v][1]+e[i].l);
dp[u][
0]=dp[u][0]+dp[v][0
]; }
dp[u][
0]=max(dp[u][0],max(dp[u][1]+node,dp[u][2
]));
}int
main()
ll l=-sum,r=sum;
while(l<=r)
mid=ans;
dfs(
1,0);
cout
<1][0].val+ans*k;
return0;
}
2018八省聯考 林克卡特樹
題目真滴皮 orz rqy 10分的暴力都沒拿到 10分直接求直徑 60分 容易?想到題目等價於求k 1條不相交的鏈 設狀態f i j 0 1 2 f i j 0 1 2 表示以第i個節點為根的子樹用了j條鏈並且根和兒子連有 0,1,2 條邊。轉移分為5類 g j cc 0 max g j cc 0...
八省聯考2018 林克卡特樹
挺簡單的一道題。原題斷k kk條邊連k kk條邊權為0 00的邊相當於尋去k 1 k 1k 1條不相交鏈出來,將它們連上得到的結果。所以我們要從原樹中選取k 1 k 1k 1條鏈出來,使得它們的權值和最大。我們發現恰好k 1 k 1k 1條鏈這個限制是比較難限制的,考慮通過凸優化二分去進行維護。由於...
八省聯考 2018 林克卡特樹
題意 求乙個凸函式的最優解。思路 好吧在題意裡已經說出來了。對於被卡斜率的,只能 orz 了。其實據說還有 12s 評測這種操作,對不起我省 5s 好吧不廢話了,看看應該怎麼做。暴力的話直接記 dp i j 0 2 表示當前做到第 i 棵子樹用了 j 條鏈並且當前點有 0 2 條出邊,轉移也好想。正...