對於一棵有邊權的樹(n 個結點 n – 1 條邊的無向連通圖),我們 按以下方法定義其 連通能力:
1、規定某結點的代價為它到其它結點的距離(簡單路徑所經過邊的權值 和)的最大值;
2、代價最小的結點的代價作為這棵樹的連通能力。
設某棵給定的樹以 1 號結點為根,問以任意結點為根的子樹的連 通能力有多大。
首先看到有關於樹上最長鏈的,能想到樹的直徑。然而題目中還有乙個最小的要求,所以也並不是直徑。可以證明代價最小的節點一定在樹的直徑上,感性理解一下不妨將題目要求的東西定義為「樹的半徑」。因為既在最長鏈上,但又能保持和兩鏈端的距離大致相等,向左移一步,到右邊鏈端的值會變大,答案也會更大,同理向右移也是。所以在中間位置最優,類似帶權中位數,成為既滿足最長距離,也滿足最小代價。
樹的直徑?->樹形dp呀
找到了直徑怎麼找中間那個點呢?
想到了lca裡面的倍增,往上跳直徑/2個長度即可
所以說知識掌握要熟練,這道題分析起來比較簡單,知識點都是學過的,可就是寫不來
#include#define n 1000005
using namespace std;
int first[n],next[n*2],to[n*2],w[n*2],tot;
int n,fa[n][21],f1[n],f2[n],dep[n];
int pos1[n],pos2[n],dis[n],d[n],ans[n];
int read()
void add(int x,int y,int z)
void dfs(int cur,int f)
else if(f1[t]+w[i]>f2[cur])
} int x=pos1[cur];
if(d[cur]=0;i--)
ans[cur]=f2[cur]+dis[x]-dis[cur];
if(f1[cur]-dis[fa[x][0]]+dis[cur]int main()
dep[1]=1,dfs(1,0);
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}
HAOI2015 樹上染色(樹形dp)
有一棵點數為 n 的樹,樹邊有邊權。給你乙個在 0 n 之內的正整數 k 你要在這棵樹中選擇 k個點,將其染成黑色,並將其他 的n k個點染成白色 將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間的距離的和的受益。問受益最大值是多少。輸入格式 第一行包含兩個整數 n,k 接下來 n 1 行...
HAOI2015 樹上染色(樹形dp,樹形揹包)
題目描述 有一棵點數為n的樹,樹邊有邊權。給你乙個在0 n之內的正整數k,你要在這棵樹中選擇k個點,將其染成黑色,並將其他的n k個點染成白色。將所有點染色後,你會獲得黑點兩兩之間的距離加上白點兩兩之間距離的和的收益。問收益最大值是多少。輸入描述 第一行兩個整數n,k。接下來n 1行每行三個正整數f...
poj 1192 最優連通子集 (樹形dp)
設dp u 0 為以u為根的子樹,子集中沒有u的最大權值,dp u 1 則表示子集中有u。如果子集中沒有u,那麼u的所有兒子中只能選乙個。如果子集中有u,那麼u的所有兒子要麼不選,要麼必須在子集中。狀態轉移方程 dp u 0 max dp u 0 max dp v 0 dp v 1 dp u 1 m...