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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

算法复习——虚树(消耗战bzoj2286)

發布時間:2024/4/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 算法复习——虚树(消耗战bzoj2286) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目:

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

?

Source

Stage2 day2

題解:

先發泄一下:

bzoj輸出量大了不能用cout!!!!!!!

bzoj輸出量大了不能用cout!!!!!!!

bzoj輸出量大了不能用cout!!!!!!!

艸艸艸艸艸艸卡了我一個下午!!!!!

接下說下關于虛樹的知識:

然后這道題就是虛樹+簡單的樹形dp即可,注意在新建虛樹邊的時候不要直接memset,否則會超時····

代碼:

#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<ctime> #include<cctype> #include<string> #include<cstring> #include<algorithm> using namespace std; const int N=250005; int dfn[N],first[N],go[N*2],nxt[N*2],tot=0,n,m,g[N][26],deep[N],cnt=0,vn,tn,tem; int tot1=0,first1[N],go1[N*2],next1[N*2],par[N],tag[N]; int vir[N],stack[N],top=0; long long dp[N],val[N*2],minn[N]; inline void comb(int a,int b,long long c) {nxt[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c;nxt[++tot]=first[b],first[b]=tot,go[tot]=a,val[tot]=c; } inline void comb1(int a,int b) {next1[++tot1]=first1[a],first1[a]=tot1,go1[tot1]=b; } inline int R() {char c;int f=0;for(c=getchar();c<'0'||c>'9';c=getchar());for(;c<='9'&&c>='0';c=getchar())f=(f<<3)+(f<<1)+c-'0';return f; } inline long long Rl() {char c;long long f=0;for(c=getchar();c<'0'||c>'9';c=getchar());for(;c<='9'&&c>='0';c=getchar())f=f*10+c-'0';return f; } inline void dfs(int u,int fa) {dfn[u]=++cnt;for(int e=first[u];e;e=nxt[e]){int v=go[e];if(v==fa) continue;deep[v]=deep[u]+1;g[v][0]=u;minn[v]=min(minn[u],val[e]);dfs(v,u);} } inline int get(int a,int b) {int i,j;if(deep[a]<deep[b]) swap(a,b);for(i=0;(1<<i)<=deep[a];i++);i--;for(j=i;j>=0;j--){if(deep[a]-(1<<j)>=deep[b])a=g[a][j];}if(a==b) return a;for(j=25;j>=0;j--){if(g[a][j]!=g[b][j]){a=g[a][j];b=g[b][j];}}return g[a][0]; } inline void pre() {tot1=0,stack[top=0]=0,tem++; } bool cmp(const int &a,const int &b) {return dfn[a]<dfn[b]; } inline void build() {sort(vir+1,vir+vn+1,cmp);vn=unique(vir+1,vir+vn+1)-vir-1;tn=vn;for(int i=1;i<=tn;i++){int u=vir[i];if(!top){par[u]=0;stack[++top]=u;continue;}int lca=get(stack[top],u);while(deep[stack[top]]>deep[lca]){if(deep[stack[top-1]]<deep[lca]) par[stack[top]]=lca;top--;}if(stack[top]!=lca){vir[++vn]=lca;par[lca]=stack[top];stack[++top]=lca;}par[u]=lca;stack[++top]=u;}sort(vir+1,vir+vn+1,cmp); } inline long long solve(int u) {if(tag[u]==tem)return minn[u];dp[u]=minn[u];long long temp=0;bool flag=false;for(int e=first1[u];e;e=next1[e]){int v=go1[e];flag=true;temp+=solve(v);}if(flag) dp[u]=min(dp[u],temp);return dp[u]; } int main() {//freopen("a.in","r",stdin);n=R(); int a,b;long long c;for(int i=1;i<n;i++){a=R(),b=R(),c=Rl();comb(a,b,c);}minn[1]=1e+18;deep[1]=1;dfs(1,0);for(int i=1;i<=25;i++)for(int j=1;j<=n;j++)g[j][i]=g[g[j][i-1]][i-1];m=R();for(int i=1;i<=m;i++){pre(),vn=R();for(int j=1;j<=vn;j++)vir[j]=R(),tag[vir[j]]=tem;build();for(int j=1;j<=vn;j++)first1[vir[j]]=dp[vir[j]]=0;for(int j=2;j<=vn;j++)comb1(par[vir[j]],vir[j]);dp[vir[1]]=solve(vir[1]);printf("%lld\n",dp[vir[1]]);}return 0; }

?

轉載于:https://www.cnblogs.com/AseanA/p/7485646.html

總結

以上是生活随笔為你收集整理的算法复习——虚树(消耗战bzoj2286)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。