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 行,每行三個數分別表示代價和,最小代價,最大代價。
2 13 2
4 15 2
6 47 5
8 69 7
10 9
5 410 4
5 26 1
6 13 3 3
6 6 6
1 1 1
2 2 2
2 2 2
n<=1000000
q<=50000並且保證所有k之和<=2*n
先考慮正常的\(dp\)
對於第乙個,總和。設\(f[i]\)表示\(i\)的子樹中的關鍵點的個數
轉移:\(sum+=f[v]*(k-f[v])*len(i,v),f[i]+=f[v]\)
對於第二個和第三個,相當於維護樹上最長鏈和最短鏈
這個就非常基礎了,不寫了。
現在再把這個\(dp\)放在虛樹上做就行了
#include#include#include#include#include#include#include#include#include#includeusing 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)
sum=0;min=1e9;max=-1e9;dp(p[1]);
printf("%lld %d %d\n",sum,min,max);
for(int i=1;i<=k;++i)vis[p[i]]=false,h[p[i]]=0;
} 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 ...