[bzoj 2286]Sdoi2011消耗战
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2286
Sdoi2011消耗战
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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
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
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