bzoj5129 點分治 最短路 樹上傳送

2021-09-08 11:50:33 字數 3328 閱讀 3331

description

扔個傳送門

題解

為什麼ozy這麼強啊…

我還打個屁啊…

一開始就想歪了想到優化建圖去了…一通魔搞之後無功而返

單考慮dij怎麼做,我們發現從堆中拿出來乙個點之後,能擴充套件的點的權是都是d[x

]+co

st[x

]d[x]+cost[x]

d[x]+c

ost[

x]於是可以堆按照d[x

]+co

st[x

]d[x]+cost[x]

d[x]+c

ost[

x]排序,這樣顯然能被擴充套件到的點一定是最小的

於是我們就需要保證每個點被擴充套件的次數小於某個定值

對這棵樹點分,每個點儲存以他為重心後bfs序開始掃的序號

當我們從堆中拿出這個點的時候,跳他的分治父親,顯然可以通過到父親的距離和bfs序開始掃的編號確定這個點到下乙個被擴充套件的點的最長距離是什麼

我們發現,在這種情況下,每個點只會被擴充套件一次

複雜度就是nlo

gn

nlogn

nlogn的了

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define ll long long

#define mp(x,y) make_pair(x,y)

#define pll pair

#define pii pair

using

namespace std;

inline

intread()

while

(ch>=

'0'&&ch<=

'9')

return x*f;

}int stack[20]

;inline

void

write

(ll x)if(

!x)int top=0;

while

(x)stack[

++top]

=x%10

,x/=10;

while

(top)

putchar

(stack[top--]+

'0');}

inline

void

pr1(

int x)

inline

void

pr2(ll x)

const

int maxn=

300005

;struct nodea[

2*maxn]

;int len,last[maxn]

;void

ins(

int x,

int y)

int first[maxn]

,log[

2*maxn]

,bin[25]

,dep[maxn]

,dfn[

2*maxn]

,id;

void

pre_tree_node

(int x,

int fa)}}

int mn[25]

[2*maxn]

;void

init()

intlca

(int x,

int y)

intdis

(int x,

int y)

vector vec[maxn]

;int begin[maxn]

;queue li;

bool vis[maxn]

;int in[maxn]

,tim;

void

bfs(

int s)

}int tot[maxn]

,f[maxn]

,totsum,g;

voidgo(

int x,

int fa)

}void

dfs(

int x,

int fa)

f[x]

=max

(f[x]

,totsum-tot[x]);

if(!g||f[x]

)g=x;

}int refa[maxn]

;void

getrt

(int x)}}

int lim[maxn]

,cost[maxn]

;priority_queue

,greater

> hp;

ll d[maxn]

;int

main()

pre_tree_node(1

,0);

init()

;memset

(vis,

true

,sizeof

(vis));

totsum=n;

dfs(1,

0);getrt

(g);

for(

int i=

1;i<=n;i++

)lim[i]

=read()

,cost[i]

=read()

;memset

(d,63

,sizeof

(d))

;d[st]=0

;memset

(vis,

false

,sizeof

(vis));

hp.push(mp

(d[st]

+cost[st]

,st));

while

(!hp.

empty()

)if(d[u1]

>d[temp]

+cost[temp])}

if(nw==-1

)begin[x]

=vec[x]

.size()

;else begin[x]

=nw;

x=refa[x];}

}for

(int i=

1;i<=n;i++

)pr2

(d[i]);

return0;

}

BZOJ4016 最短路徑樹問題(點分治)

題解 先跑乙個最短路圖,然後按照結點編號從小到大dfs一遍,dfs樹即為題目所要求。然後就是點分治的經典做法,路徑分為經過根節點的和不經過根節點的,不經過根節點的路徑一定屬於其某個子樹中,分治來做。include include include include include include inc...

bzoj3694 最短路 樹鏈剖分

給出乙個n個點m條邊的無向圖,n個點的編號從1 n,定義源點為1。定義最短路樹如下 從源點1經過邊集t到任意一點i有且僅有一條路徑,且這條路徑是整個圖1到i的最短路徑,邊集t構成最短路樹。給出最短路樹,求對於除了源點1外的每個點i,求最短路,要求不經過給出的最短路樹上的1到i的路徑的最後一條邊。第一...

bzoj 2125 最短路 樹鏈剖分

好吧實際上和樹剖沒什麼關係。只是用來求lca的。對於點x,如果不在環中,定義它的父親為dfs樹中的父親 否則定義它的父親為它所在環在dfs樹中最高的點,同時距離為它到那個最高點的最短路。然後可以用樹剖求出 x,y 的lca。然後分類討論一下,因為如果x lca和y lca的路徑上最後一部分在乙個環中...