BZOJ 2286 消耗戰(虛樹)

2021-07-04 01:55:10 字數 1584 閱讀 6890

因為聽說多校第一場的09可以用虛樹來做,於是趕緊趁著沒比賽補一發相關知識點。

臥槽寫完這篇題解之後,突然發現多校09題解給的方法不就是維護一顆動態虛樹嘛!

只不過說虛樹是動態的,你需要將點插入虛樹中,就要動態維護這個樹的權值。

事實上虛樹就是通過重新建樹,使得樹上的「無用決策點」全部去掉(當然相關資訊必須要之前就維護好)。

虛樹的構建方法

code:

#includeusing namespace std;

typedef long long ll;

const ll inf = 1e17;

const int n = 250005;

const int m = 19;

struct edge;

edge e[n << 1];

int head[n],sz;

int fa[n][m],dep[n];

int dfn[n],time;

ll cost[n];

inline bool cmp1(int x,int y)

inline bool cmp2(int x,int y)

void init()

void addedge(int u,int v,ll c)

void dfs(int u,int f)

}int find(int x,int k)

int lca(int x,int y)

x = fa[x][0];

y = fa[y][0];

}return x;

}/*}}}*/

int n,m;

int h[n],t[n],tot;

int father[n],son[n];

int s[n],top;

ll dp[n];

void build(int k)

else

if(anc != s[top])

father[p] = s[top];

t[++ tot] = p;

s[++ top] = p;}}

}/*}}}*/

void debug()

void deal()

sort(h + 1,h + k + 1,cmp1);

build(k);

sort(t + 1,t + tot + 1,cmp2);

son[0] = dp[0] = 0;

for(int i = 1 ; i <= tot ; i ++)

son[ t[i] ] = dp[ t[i] ] = 0;

for(int i = 1 ; i <= k ; i ++)

son[ h[i] ] = 1,dp[ h[i] ] = inf;

for(int i = 1 ; i <= tot ; i ++)

printf("%lld\n",dp[ t[tot] ]);

}void solve()

dfs(1,0);

scanf("%d",&m);

while(m --) deal();

}int main()

bzoj2286 消耗戰 虛樹 樹形dp

解題思路 假如只有一次詢問,可以很好想到樹形dp方程 如果u是關鍵點,則f u w fa u u 如果u不是關鍵點,則f u min w fa u u f son u 但這樣一次複雜度為o n 則總複雜度為o nm 顯然超時。像這種每次詢問都給出多個關鍵點的題,應該建虛樹,即每次詢問都只把關鍵點及其...

BZOJ2286 消耗戰(虛樹,樹形dp)

今天本tu生日,學個新演算法慶祝一下。學了虛樹,碰到每次詢問給你一些點點的樹就不虛了 對於一棵樹,我們可以在上面用我們學過的演算法為所欲為。假設題目有多個詢問,每個詢問給出了一些點,那我們可以把這些點和及有關係的點拉出來,合併點和邊的資訊,構出虛樹,在虛樹上繼續為所欲為。對於與詢問有關係的點,就是這...

消耗戰 dp 虛樹

題目描述 在一場戰爭中,戰場由 n 個島嶼和 n 1 個橋梁組成,保證每兩個島嶼間有且僅有一條路徑可達。現在,我軍已經偵查到敵軍的總部在編號為 1 的島嶼,而且他們已經沒有足夠多的能源維繫戰鬥,我軍勝利在望。已知在其他 k 個島嶼上有豐富能源,為了防止敵軍獲取能源,我軍的任務是炸毀一些橋梁,使得敵軍...