BZOJ2286: [Sdoi2011]消耗戰(虛樹)


BZOJ2286: [Sdoi2011]消耗戰

  Time Limit: 20 Sec
  Memory Limit: 512 MB

Description

  在一場戰爭中,戰場由n個島嶼和n-1個橋梁組成,保證每兩個島嶼間有且僅有一條路徑可達。現在,我軍已經偵查到敵軍的總部在編號為1的島嶼,而且他們已經沒有足夠多的能源維系戰斗,我軍勝利在望。已知在其他k個島嶼上有豐富能源,為了防止敵軍獲取能源,我軍的任務是炸毀一些橋梁,使得敵軍不能到達任何能源豐富的島嶼。由于不同橋梁的材質和結構不同,所以炸毀不同的橋梁有不同的代價,我軍希望在滿足目標的同時使得總代價最小。
  偵查部門還發現,敵軍有一臺神秘機器。即使我軍切斷所有能源之后,他們也可以用那臺機器。機器產生的效果不僅僅會修復所有我軍炸毀的橋梁,而且會重新隨機資源分布(但可以保證的是,資源不會分布到1號島嶼上)。不過偵查部門還發現了這臺機器只能夠使用m次,所以我們只需要把每次任務完成即可。
 

Input

  第一行一個整數n,代表島嶼數量。
  接下來n-1行,每行三個整數u,v,w,代表u號島嶼和v號島嶼由一條代價為c的橋梁直接相連,保證1<=u,v<=n且1<=c<=100000。
  第n+1行,一個整數m,代表敵方機器能使用的次數。
  接下來m行,每行一個整數ki,代表第i次后,有ki個島嶼資源豐富,接下來k個整數h1,h2,…hk,表示資源豐富島嶼的編號。
 

Output

  輸出有m行,分別代表每次任務的最小代價。
 

Sample Input

  10
  1 5 13
  1 9 6
  2 1 19
  2 4 8
  2 3 91
  5 6 8
  7 5 4
  7 8 31
  10 7 9
  3
  2 10 6
  4 5 7 8 3
  3 9 4 6
 

Sample Output

  12
  32
  22
    

HINT

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

題目地址:  BZOJ2286: [Sdoi2011]消耗戰

題目大意: 已經很簡潔了

題解:

  裸的虛樹
  
  虛樹的概念
  虛樹,就是在有一棵樹的情況下,對于數量較少的點進行詢問時所建的一棵新的樹,虛樹包含詢問的點和詢問的點的lca(最近公共祖先),上面的點被稱為關鍵點。對于兩個關鍵點A,B,它們的連邊上包含著原本樹上兩點之間那條鏈上的關鍵信息(這個信息可以是邊權最大值、邊權最小值、或者是邊權之和,這個取決于實際需要),然后就可以進行樹形dp了,這樣的復雜度是基于詢問的點數的,就可以想象虛樹就是把一棵大樹濃縮成一棵擁有所有你需要的信息的小樹。
  
  建樹的方法
那么怎么建樹呢,比較常見的做法是維護一個棧,里面存儲著一條鏈,每一次加入一個點進行操作。
具體列舉一下步驟吧
  
  預備知識:
  用較優的復雜度求lca,以及求兩點之間的距離,一般倍增做,或者樹鏈剖分加前綴和都可以,這都是單次O(logn)的,另外呢,要事先求好原樹的dfs序和每個點的深度(這里的深度是指點序的深度,在計算這個深度的時候每條邊都是為1來算),后面要用
  
  詢問操作:
  1.輸入每個詢問的點,并且按照dfs序為關鍵字排序
  2.將第1個點壓到棧當中,開始構建虛樹
  3.枚舉到下一個點u,計算u與棧頂點v的公共祖先lca
  4.假設棧中棧頂下方的點為w(若棧中只有1個點就直跳過這一步),若w點的深度大于lca就把v向w連一條邊,并且彈掉v,重復此步,否則就到下一步
  5.若lca不是當前的v,那么就把lca和v連邊,把v彈出,讓lca成為棧頂元素(注:這個操作的意思是如果棧頂沒有這個lca那么就壓入),否則不做任何操作
  6.最后把u壓入棧中
  7.回到3操作枚舉下個點,直到枚舉完了所有點
  8.把棧頂v與棧頂下方的點為w連邊,并且把v彈掉,這么做直到棧里只有一個點
  9.棧里剩下的點就是虛樹的根了
  接下來你就可以開始進行dp等操作了
  
  虛樹的復雜度
  虛樹的建樹的復雜度是O(k?log(n))的,樹形dp就是O(k)的啦,因為考慮最后虛樹上的關鍵點有詢問的點,和lca,然后每個詢問的點最多產生1個新的lca,所以復雜度就是對的啦
  
  來自https://blog.csdn.net/zhouyuheng2003/article/details/79110326
  大神的博客里寫的很清楚了,具體看代碼實現吧:)
  
  此題很容易發現用 dp 解決
  但是多組詢問 \(O(nm)\) 會TLE
  重新建圖把點縮少再跑 dp 就好了
  具體看代碼實現吧:)


AC代碼

#include <cstdio> 
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int N=250005;
const ll inf=5e10;
int n,Q,K,top,ind;
int a[N],h[N];
int cnt,_cnt,last[N],_last[N];
inline int read(){int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x;
}
struct edge{int to,val,next;
}e[N<<1];
struct _edge{int to,next;
}_e[N];
void add_edge(int u,int v,int w){e[++cnt]=(edge){v,w,last[u]};last[u]=cnt;e[++cnt]=(edge){u,w,last[v]};last[v]=cnt;
}
void _add_edge(int u,int v){if(u==v)return;_e[++_cnt]=(_edge){v,_last[u]};_last[u]=_cnt;
}
int pos[N],dep[N],fa[N][20];
ll mn[N];
void dfs(int u){pos[u]=++ind;for(int i=last[u];i;i=e[i].next){int v=e[i].to;if(v==fa[u][0])continue;fa[v][0]=u;dep[v]=dep[u]+1;mn[v]=min(mn[u],(ll)e[i].val);dfs(v);}
}
int lca(int a,int b){if(dep[a]<dep[b])swap(a,b);for(int i=18;i>=0;i--)if(dep[fa[a][i]]>=dep[b])a=fa[a][i];for(int i=18;i>=0;i--)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];if(a==b)return a;return fa[a][0];
}
bool cmp(int a,int b){return pos[a]<pos[b];
}
ll f[N];
void DP(int u){f[u]=mn[u];ll tmp=0;for(int i=_last[u];i;i=_e[i].next){int v=_e[i].to;DP(v);tmp+=f[v];}_last[u]=0;if(tmp!=0)f[u]=min(f[u],tmp);
}
int q[N];
void solve(){_cnt=0;K=read();for(int i=1;i<=K;i++)h[i]=read();sort(h+1,h+K+1,cmp);int tot=0;h[++tot]=h[1];for(int i=2;i<=K;i++)if(lca(h[tot],h[i])!=h[tot])h[++tot]=h[i];top=0;q[++top]=1;for(int i=1;i<=tot;i++){int now=h[i],F=lca(now,q[top]);while(1){if(dep[F]>=dep[q[top-1]]){_add_edge(F,q[top--]);if(q[top]!=F)q[++top]=F;break;}_add_edge(q[top-1],q[top]);top--;}if(q[top]!=now)q[++top]=now;}while(--top)_add_edge(q[top],q[top+1]);DP(1);printf("%lld\n",f[1]);
}
int main(){n=read();for(int i=1;i<n;i++){int u=read(),v=read(),w=read();add_edge(u,v,w);}mn[1]=inf;dep[1]=1;dfs(1);for(int j=1;j<=18;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];Q=read();while(Q--)solve();return 0;
}


  作者:skl_win
  出處:https://www.cnblogs.com/shaokele/
  本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

轉載于:https://www.cnblogs.com/shaokele/p/9507627.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/397155.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397155.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397155.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基礎知識:Java實現Map集合二級聯動4

comboBox.setModel(new DefaultComboBoxModel(getProvince())); // 添加省份信息 final JLabel label new JLabel(); label.setText("省/直轄市"); label.setBounds(155, 30, 66, 18); panel.add(label); final JLabel label_1 new JLabel(); label_1.setText(&quo…

linux QT 結束當前進程_Qt編寫控件屬性設計器7-串口采集

一、前言數據源是組態軟件的核心靈魂&#xff0c;少了數據源&#xff0c;組態就是個花架子沒卵用&#xff0c;一般數據源有三種方式獲取&#xff0c;串口、網絡、數據庫&#xff0c;至于數據規則是什么&#xff0c;這個用戶自己指定&#xff0c;本設計器全部采用第一個字節作為…

magento2郵件調試方法

order mail 直接打印到頁面上 位置 vendor\magento\module-sales\Model\Order\Email\Sender.php Magento\Sales\Model\Order\Email\Sender::prepareTemplate() 添加代碼 $objectManager \Magento\Framework\App\ObjectManager::getInstance(); $templateFactory $objectManag…

python多進程怎么樣_Python執行多進程任務的方法

Python的多進程可以借助from multiprocessing import Pool來實現。簡而言之分為這樣幾步&#xff1a;導入包from multiprocessing import Pool編寫任務函數。def 任務函數(參數)實例化進程池并設置進程數。poolPool(欲設置的進程數)開始布置任務&#xff0c;把多個任務添加進多…

JAVA多線程之Synchronize 關鍵字原理

image眾所周知 Synchronize 關鍵字是解決并發問題常用解決方案&#xff0c;有以下三種使用方式: 同步普通方法&#xff0c;鎖的是當前對象。同步靜態方法&#xff0c;鎖的是當前 Class 對象。同步塊&#xff0c;鎖的是 {} 中的對象。實現原理&#xff1a;JVM 是通過進入、退出對…

iOS-數據持久化-第三方框架FMDB的使用

FMDB簡單介紹 一、簡單說明 1.什么是FMDB FMDB是iOS平臺的SQLite數據庫框架 FMDB以OC的方式封裝了SQLite的C語言API 2.FMDB的優點 使用起來更加面向對象&#xff0c;省去了很多麻煩、冗余的C語言代碼 對比蘋果自帶的Core Data框架&#xff0c;更加輕量級和靈活 提供了多線程安全…

電腦word文檔打不開怎么辦_word怎么轉pdf?兩個值得學習的高效轉換法

word怎么轉pdf&#xff1f;兩個值得學習的高效轉換法word怎么轉pdf&#xff1f;pdf格式是我們經常能夠使用到的格式&#xff0c;因為pdf格式在傳遞的過程中能更好地避免文件出現亂碼打不開或誤觸導致文件被修改的情況。那如果想要把word文件轉換成pdf格式以避免閱讀word時文件被…

sql server常用函數、常用語句

一、常用函數 1.字符串函數 &#xff1a; charindex(:,abc:123) --尋找一個字符在一段字符串中起始的位置 len(zhangsan) --獲取一段字符串的長度 left(Ly,君子之耀,2) --從一段字符串左邊返回指定長度的字符 right(char_expr,int_expr) --返回字符串右邊int_expr個字符 …

python 矩陣乘法 跳過nan_python – Numpy:當一些向量元素等于零時,矩陣向量乘法不會跳過計算嗎?...

我最近一直致力于一個項目,其中我的大部分時間花費在密集矩陣A和稀疏向量v上(見here).在我嘗試減少計算時,我注意到A.dot(v)的運行時間不受v的零條目數的影響.為了解釋為什么我希望在這種情況下改進運行時,讓result A.dot.v使得j 1的結果[j] sum_i(A [i,j] * v [j])… v.sha…

[轉]Responsive Tables Demo

本文轉自&#xff1a;http://elvery.net/demo/responsive-tables/ A quick and dirty look at some techniques for designing responsive table layouts. This was put together in haste (and with the aid of Twitter Bootstrap) for What Do You Know Brisbane hosted by W…

Scala函數式對象-有理數

有理數類的表示 實現規范&#xff1a;支持有理數的加減乘除&#xff0c;并支持有理數的規范表示 1.定義Rational 首先&#xff0c;考慮用戶如何使用這個類&#xff0c;我們已經決定使用“Immutable”方式來使用Rational對象&#xff0c;我們需要用戶在定義Rational對象時提供分…

2020雙十一實時大屏_2020拼多多雙十一,拼多多雙十一活動

2020拼多多雙十一&#xff0c;拼多多雙十一活動&#xff0c;2020拼多多雙十一&#xff0c;拼多多雙十一活動2020拼多多雙十一&#xff0c;拼多多雙十一活動拼多多雙11來了全球狂歡節先領券再購物低價風暴 震撼來襲沒有最低 只有更低拼多多優惠券商城拼多多優惠商城&#xff0c;…

dataTables本地刷新數據解決只能初始化一次問題

2019獨角獸企業重金招聘Python工程師標準>>> dataTables的表格只能初始化一次&#xff0c;這樣如果需要動態改變表格數據的話就需要寫多個表格&#xff0c;這樣很顯然不是一個好的解決方案。 dataTables Api提供了刷新數據解決方案&#xff1a; 這里大概說一下案例&…

安裝Ubuntu版本linux過程中沒有提示設置root用戶密碼問題的解決辦法

原來ubunto不提倡設置root用戶&#xff0c;系統安裝成功后&#xff0c;root密碼是隨機的&#xff0c;那么在這種情況下如何得到root權限吶&#xff0c;具體方法如下&#xff1a; 終端中輸入&#xff1a;sudo passwd root 此時重新設置原登錄用戶的密碼。 設置成功后在終端繼續輸…

linux命令headtail

一、head語法head [-n -k ]... [FILE]...//k是數字默認是顯示開頭前10行。head /etc/passwd顯示開頭前5行head -5 /etc/passwdhead -n 5 /etc/passwd&#xff08;注意和以下的有-的差別&#xff09;head -n 5 /etc/passwd 除最后k行外&#xff0c;顯示剩余所有內容。head -n -5…

用-force –opengl 指令_蘋果新系統ios14新功能匯總 輕點背面等小技巧怎么用

在 iOS 14 以及更新系統中&#xff0c;蘋果為 iPhone X 以及更新機型帶來了“輕點背面”功能&#xff0c;可以讓用戶輕點手機背面來實現更多操作&#xff0c;并且這項功能還支持“快捷指令”。例如&#xff0c;如果您不希望應用讀取剪貼板中私密內容&#xff0c;可以利用“輕點…

PE文件格式(加密與解密3)(一)

本次的了解主要講解 PE的基本概念、MS-DOS文件頭、PE文件頭、區塊、輸入表、輸出表等。 這里我將會結合一個簡單的小程序來加深我對PE文件結構的了解。 使用學習工具&#xff1a;有StudyPE、LordPE、PEID。 學習PE建議看書。。和自己動手。。。 PE文件&#xff1a; 在WIN上&…

mysql用戶_MySQL用戶權限管理詳解

用戶權限管理主要有以下作用&#xff1a;1. 可以限制用戶訪問哪些庫、哪些表2. 可以限制用戶對哪些表執行SELECT、CREATE、DELETE、DELETE、ALTER等操作3. 可以限制用戶登錄的IP或域名4. 可以限制用戶自己的權限是否可以授權給別的用戶一、用戶授權mysql> grant all privile…

對ContentProvider中getType方法的一點理解

在上篇博客中我們介紹了自定義ContentProvider&#xff0c;但是遺漏掉了一個方法&#xff0c;那就是getType&#xff0c;自定義ContentProvider一般用不上getType方法&#xff0c;但我們還是一起來探究下這個方法究竟是干什么的&#xff1f;我們先來看看ContentProvider中對這個…

手把手教Electron+vue的使用

.現如今前端框架數不勝數&#xff0c;尤其是angular、vue吸引一大批前端開發者&#xff0c;在這個高新技術快速崛起的時代&#xff0c;自然少不了各種框架的結合使用。接下來是介紹electronvue的結合使用。 2.Electron是什么&#xff1f;&#xff1f; 對于我來說Electron相當于…