bzoj
國家有乙個大工程,要給乙個非常大的交通網路裡建一些新的通道。
我們這個國家位置非常特殊,可以看成是乙個單位邊權的樹,城市位於頂點上。
在 2 個國家 a,b 之間建一條新通道需要的代價為樹上 a,b 的最短路徑。
現在國家有很多個計畫,每個計畫都是這樣,我們選中了 k 個點,然後在它們兩兩之間 新建 c(k,2)條 新通道。
現在對於每個計畫,我們想知道:
1.這些新通道的代價和
2.這些新通道中代價最小的是多少
3.這些新通道中代價最大的是多少
第一行 n 表示點數。
接下來 n-1 行,每行兩個數 a,b 表示 a 和 b 之間有一條邊。
點從 1 開始標號。 接下來一行 q 表示計畫數。
對每個計畫有 2 行,第一行 k 表示這個計畫選中了幾個點。
第二行用空格隔開的 k 個互不相同的數表示選了哪 k 個點。
輸出 q 行,每行三個數分別表示代價和,最小代價,最大代價。
10 2 1
3 2
4 1
5 2
6 4
7 58 6
9 7
10 9
5 2
5 4
2 10 4
2 5 2
2 6 1
2 6 1
3 3 3
6 6 6
1 1 1
2 2 2
2 2 2
n<=1000000
q<=50000並且保證所有k之和<=2*n
先考慮正常的dp
d
p對於第乙個,總和。設f[
i]f [i
]表示
i i
的子樹中的關鍵點的個數
轉移:sum
+=f[
v]∗(
k−f[
v])∗
len(
i,v)
,f[i
]+=f
[v]' role="presentation">sum
+=f[
v]∗(
k−f[
v])∗
len(
i,v)
,f[i
]+=f
[v]s
um+=
f[v]
∗(k−
f[v]
)∗le
n(i,
v),f
[i]+
=f[v
]對於第二個和第三個,相當於維護樹上最長鏈和最短鏈
這個就非常基礎了,不寫了。
現在再把這個dp
d
p放在虛樹上做就行了
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define ll long long
#define rg register
#define max 1001000
inline
int read()
struct linee[max<<1];
int h[max],cnt=1;
inline
void add(int u,int v,int w);h[u]=cnt++;}
int n,q,k;
int fa[max],size[max],hson[max],dep[max],top[max],dfn[max],low[max],tim;
void dfs1(int u,int ff)
}void dfs2(int u,int tp)
low[u]=tim;
}int lca(int u,int v)
}int main()
dfs1(1,0);dfs2(1,1);
memset(h,0,sizeof(h));
q=read();
while(q--)
return
0;}
BZOJ3611 大工程(虛樹,動態規劃)
bzoj 國家有乙個大工程,要給乙個非常大的交通網路裡建一些新的通道。我們這個國家位置非常特殊,可以看成是乙個單位邊權的樹,城市位於頂點上。在 2 個國家 a,b 之間建一條新通道需要的代價為樹上 a,b 的最短路徑。現在國家有很多個計畫,每個計畫都是這樣,我們選中了 k 個點,然後在它們兩兩之間 ...
bzoj3611 大工程 虛樹 dp
國家有乙個大工程,要給乙個非常大的交通網路裡建一些新的通道。我們這個國家位置非常特殊,可以看成是乙個單位邊權的樹,城市位於頂點上。在 2 個國家 a,b 之間建一條新通道需要的代價為樹上 a,b 的最短路徑。現在國家有很多個計畫,每個計畫都是這樣,我們選中了 k 個點,然後在它們兩兩之間 新建 c ...
Luogu P4103大工程(虛樹DP)
題目鏈結 我貌似發現這類dp就是先別管什麼虛樹 把樹形dp搞出來套上虛樹板子就好了 這個樹形dp就是設sum為答案,sumd為子樹內所有點的深度和 當然指的是被詢問的點 maxi指子樹內最深的點的深度,mini同理 然後考慮我們dfs到x,它的兒子已經遍歷到一半,新加進來乙個兒子to 顯然 sum ...