日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Luogu2495[SDOI2011]消耗战

發(fā)布時(shí)間:2024/1/17 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Luogu2495[SDOI2011]消耗战 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題目描述

在一場戰(zhàn)爭中,戰(zhàn)場由\(n\)島嶼和\(n-1\)個(gè)橋梁組成,保證每兩個(gè)島嶼間有且僅有一條路徑可達(dá)。現(xiàn)在,我軍已經(jīng)偵查到敵軍的總部在編號(hào)為\(1\)的島嶼,而且他們已經(jīng)沒有足夠多的能源維系戰(zhàn)斗,我軍勝利在望。已知在其他\(k\)個(gè)島嶼上有豐富能源,為了防止敵軍獲取能源,我軍的任務(wù)是炸毀一些橋梁,使得敵軍不能到達(dá)任何能源豐富的島嶼。由于不同橋梁的材質(zhì)和結(jié)構(gòu)不同,所以炸毀不同的橋梁有不同的代價(jià),我軍希望在滿足目標(biāo)的同時(shí)使得總代價(jià)最小。

偵查部門還發(fā)現(xiàn),敵軍有一臺(tái)神秘機(jī)器。即使我軍切斷所有能源之后,他們也可以用那臺(tái)機(jī)器。機(jī)器產(chǎn)生的效果不僅僅會(huì)修復(fù)所有我軍炸毀的橋梁,而且會(huì)重新隨機(jī)資源分布(但可以保證的是,資源不會(huì)分布到\(1\)號(hào)島嶼上)。不過偵查部門還發(fā)現(xiàn)了這臺(tái)機(jī)器只能夠使用\(m\)次,所以我們只需要把每次任務(wù)完成即可。

輸入格式:

第一行一個(gè)整數(shù)\(n\),代表島嶼數(shù)量。

接下來\(n-1\)行,每行三個(gè)整數(shù)\(u\),\(v\),\(w\),代表\(u\)號(hào)島嶼和\(v\)號(hào)島嶼由一條代價(jià)為\(c\)的橋梁直接相連,保證\(1<=u,v<=n\)\(1<=c<=100000\)

\(n+1\)行,一個(gè)整數(shù)\(m\),代表敵方機(jī)器能使用的次數(shù)。

接下來\(m\)行,每行一個(gè)整數(shù)\(ki\),代表第\(i\)次后,有\(ki\)個(gè)島嶼資源豐富,接下來\(k\)個(gè)整數(shù)\(h1,h2,…h(huán)k\),表示資源豐富島嶼的編號(hào)。

輸出格式:

輸出有\(m\)行,分別代表每次任務(wù)的最小代價(jià)。

【數(shù)據(jù)規(guī)模和約定】

對于\(10\%\)的數(shù)據(jù),\(2<=n<=10,1<=m<=5,1<=ki<=n-1\)

對于\(20\%\)的數(shù)據(jù),\(2<=n<=100,1<=m<=100,1<=ki<=min(10,n-1)\)

對于\(40\%\)的數(shù)據(jù),\(2<=n<=1000,m>=1,sigma(ki)<=500000,1<=ki<=min(15,n-1)\)

對于\(100\%\)的數(shù)據(jù),\(2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1\)


題目中\(k\)的總數(shù)有\(500000\),顯然虛樹優(yōu)化樹形\(DP\).因?yàn)槭堑谝淮螌懱摌渌猿隽瞬簧?span id="ozvdkddzhkzd" class="math inline">\(bug\),這里來總結(jié)一下怎么寫虛樹.

首先,你要能建立出樹形\(DP\)的樸素模型

在此基礎(chǔ)上,由于詢問點(diǎn)數(shù)和有限,所以我們并不需要對每次詢問都\(O(N)\)\(DP\)回答.這里我們進(jìn)行一次\(DFS\)的預(yù)處理,只抽出有效信息的一顆濃縮的樹.那么關(guān)鍵就在怎么把它抽出來了.

對這個(gè)題,我們可以記錄一個(gè)根節(jié)點(diǎn)到每個(gè)節(jié)點(diǎn)的最窄部分.然后對詢問點(diǎn)按照\(dfs\)序排序.排序過后,對每兩個(gè)\(dfs\)序相鄰節(jié)點(diǎn)求\(lca\)扔進(jìn)要用的點(diǎn)里.(可以口胡得到:這樣一定涵蓋所有必要的\(LCA\))再按\(dfs\)序排一次序,然后就可以愉快地建樹\(DP\)啦.

Code:

#include <bits/stdc++.h> #define int long long #define N 250010 using namespace std;int n, m, k, u, v, w, cnt, val[N], head[N];int ss[N << 1], sta[N << 1], deep[N], ff[N][22], done[N];struct edge {int nxt, to, w; }e[N << 1];void add_edge (int from, int to, int val) {e[++cnt].nxt = head[from];e[cnt].to = to;e[cnt].w = val;head[from] = cnt; }int dfn[N], low[N], _dfn = 0;void pre (int u, int fa) {dfn[u] = ++_dfn;deep[u] = deep[fa] + 1;ff[u][0] = fa;for (int i = 1; (1 << i) <= deep[u]; ++i) {ff[u][i] = ff[ff[u][i - 1]][i - 1];}for (int i = head[u]; i; i = e[i].nxt) {int v = e[i].to;if (v != fa) {val[v] = min (val[u], e[i].w);pre (v, u);// printf ("val[%lld] = min (%lld, %lld)\n", v, val[u], e[i].w);}}low[u] = _dfn; }bool cmp (const int &lhs, const int &rhs) {return dfn[lhs] < dfn[rhs]; }int lca (int u, int v) {// printf ("lca (%lld, %lld) = ", u, v);if (deep[u] < deep[v]) swap (u, v);for (int i = 20; i >= 0; --i) {if (deep[ff[u][i]] >= deep[v]) {u = ff[u][i];}}if (u == v) return u;for (int i = 20; i >= 0; --i) {if (ff[u][i] != ff[v][i]) {u = ff[u][i];v = ff[v][i];}}//printf ("%lld\n", ff[u][0]);return ff[u][0]; }int get_ans (int u, int fa) {if (done [u]) return val[u];int res = 0;for (int i = head[u]; i; i = e[i].nxt) {int v = e[i].to;if (v != fa) {res += get_ans (v, u);}}return min (res, val[u]); }signed main () {//freopen ("2495.in", "r", stdin);scanf ("%lld", &n);for (int i = 1; i < n; ++i) {scanf ("%lld %lld %lld", &u, &v, &w);add_edge (u, v, w);add_edge (v, u, w);}memset (val, 0x3f, sizeof (val));pre (1, 0);/*for (int i = 1; i <= n; ++i) {printf ("node = %lld, val = %lld, low = %lld, dfn = %lld\n", i, val[i], low[i], dfn[i]);} */memset (head, 0, sizeof (head));scanf ("%lld", &m);for (int i = 1; i <= m; ++i) {// printf ("ask = %lld\n", i);scanf ("%lld", &k);for (int j = 1; j <= k; ++j) {scanf ("%lld", &ss[j]);done[ss[j]] = true;}sort (ss + 1, ss + 1 + k, cmp);for (int j = k; j > 1; --j) {ss[++k] = lca (ss[j], ss[j - 1]);}ss[++k] = 1;sort (ss + 1, ss + 1 + k, cmp);k = unique (ss + 1, ss + 1 + k) - ss - 1;int top = 0; cnt = 0;for (int j = 1; j <= k; ++j) {while (top && low[sta[top]] < dfn[ss[j]]) --top;add_edge (sta[top], ss[j], val[j]);add_edge (ss[j], sta[top], val[j]);sta[++top] = ss[j];}get_ans (1, 0);//print_tree (1, 0);printf ("%lld\n", get_ans (1, 0));for (int j = 1; j <= k; ++j) {//printf ("dp[%lld] = %lld\n", ss[j], dp[ss[j]]);done[ss[j]] = false, head[ss[j]] = 0;}} }

轉(zhuǎn)載于:https://www.cnblogs.com/maomao9173/p/10359469.html

總結(jié)

以上是生活随笔為你收集整理的Luogu2495[SDOI2011]消耗战的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。