[bzoj 2286]Sdoi2011消耗战

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj 2286]Sdoi2011消耗战相关的知识,希望对你有一定的参考价值。

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2286

Sdoi2011消耗战

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 3264  Solved: 1183
[Submit][Status][Discuss]

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

虚树学一发。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 struct _IO{
  4     int read(){
  5         int rt=0,fl=1;char ch=getchar();
  6         while(ch<0||ch>9){if(ch==-)fl=-1;ch=getchar();}
  7         while(ch>=0&&ch<=9){rt=rt*10+ch-0;ch=getchar();}
  8         return rt*fl;
  9     }
 10     _IO operator >> (int &x){
 11         x = read();
 12         return *this;
 13     }
 14     _IO operator << (long long x){
 15         printf("%lld",x);
 16         return *this;
 17     }
 18     _IO operator << (int x){
 19         printf("%d",x);
 20         return *this;
 21     }
 22     _IO operator << (const char *str){
 23         printf("%s",str);
 24         return *this;
 25     }
 26 }io;
 27 const long long inf = 0x7fffffffffffffff;
 28 typedef long long ll;
 29 const int maxn = 250005;
 30 struct edge{
 31     int to,nx,val;
 32 }e[maxn<<1];
 33 int head[maxn],cnt;
 34 int sz[maxn],ch[maxn],dep[maxn],fa[maxn],tp[maxn];
 35 ll d[maxn],mn[maxn];
 36 int st[maxn],_t,h[maxn],dfn[maxn],dfs_clock;
 37 bool cmp(int a,int b){
 38     return dfn[a]<dfn[b];
 39 }
 40 void add_edge(int u,int v,int c){
 41     if(u==v)return;
 42     e[++cnt].to=v;e[cnt].val=c;e[cnt].nx=head[u];head[u]=cnt;
 43 }
 44 void dfs1(int u){
 45     sz[u]=1;dfn[u]=++dfs_clock;
 46     for(int i=head[u];i;i=e[i].nx){
 47         if(e[i].to==fa[u])continue;
 48         int t = e[i].to;
 49         dep[t]=dep[u]+1;fa[t]=u;mn[t]=min(mn[u],(ll)e[i].val);
 50         dfs1(t);
 51         sz[u]+=sz[t];
 52         if(sz[ch[u]] < sz[t])ch[u]=t;
 53     }
 54 }
 55 void dfs2(int u,int top){
 56     tp[u]=top;
 57     if(ch[u])dfs2(ch[u],top);
 58     for(int i=head[u];i;i=e[i].nx){
 59         int t = e[i].to;
 60         if(t==ch[u]||t==fa[u])continue;
 61         dfs2(t,t);
 62     }
 63 }
 64 int lca(int u,int v){
 65     while(tp[u]!=tp[v])dep[tp[u]]>dep[tp[v]]?u=fa[tp[u]]:v=fa[tp[v]];
 66     return dep[u]>dep[v]?v:u;
 67 }
 68 void dp(int u){
 69     ll tmp=0;
 70     for(int i=head[u];i;i=e[i].nx){
 71         dp(e[i].to);
 72         tmp += d[e[i].to];
 73     }
 74     head[u]=0;
 75     if(!tmp)d[u]=mn[u];
 76     else d[u]=min(tmp,mn[u]);
 77 }
 78 void solve(){
 79     cnt=0;int k;
 80     io>>k;
 81     for(int i=1;i<=k;i++)io>>h[i];
 82     sort(h+1,h+1+k,cmp);
 83     int tot=1;
 84     for(int i=2;i<=k;i++){
 85         if(lca(h[tot],h[i])!=h[tot])
 86             h[++tot]=h[i];
 87     }
 88     st[++_t]=1;
 89     for(int i=1;i<=tot;i++){
 90         int now = h[i],f=lca(now,st[_t]);
 91         while(1){
 92             if(dep[f]>=dep[st[_t-1]]){
 93                 add_edge(f,st[_t--],0);
 94                 if(f!=st[_t])
 95                     st[++_t]=f;
 96                 break;
 97             }
 98             add_edge(st[_t-1],st[_t],0);
 99             _t--;
100         }
101         if(st[_t]!=now)st[++_t]=now;
102     }
103     while(--_t)add_edge(st[_t],st[_t+1],0);
104     dp(1);
105     io<<d[1]<<"\n";
106 }
107 int main(){
108     int n,u,v,w;
109     io>>n;
110     for(int i=1;i<n;i++){
111         io>>u>>v>>w;
112         add_edge(u,v,w);
113         add_edge(v,u,w);
114     }
115     int m;
116     io>>m;
117     mn[1]=inf;
118     dfs1(1);dfs2(1,1);
119     memset(head,0,sizeof head);
120     while(m--)solve();
121     return 0;
122 }
123 

 

以上是关于[bzoj 2286]Sdoi2011消耗战的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2286: [Sdoi2011]消耗战

Bzoj2286--Sdoi2011消耗战

[BZOJ2286][Sdoi2011]消耗战

BZOJ2286[Sdoi2011]消耗战 虚树

bzoj 2286: [Sdoi2011]消耗战

bzoj2286 [Sdoi2011]消耗战