2286: [Sdoi2011消耗战
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2082 Solved: 736
[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
Source
虚树入门题,如果你想知道虚树如何构造:http://user.qzone.qq.com/872191552/main
DP
记dis[i]为点i到根节点的路径中最小的边的权值
f[i]=min(dis[i],sigma f[son[i]]);
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<vector> 8 #include<stack> 9 #define maxn 500100 10 #define llg long long 11 using namespace std; 12 struct node 13 { 14 llg df,po; 15 }d[maxn]; 16 llg i,j,k,n,m,p[maxn][22],dad[maxn],bj[maxn],dfs[maxn],cnt,T,deep[maxn],dis[maxn],se[maxn],q,ss[maxn],open,dl[maxn]; 17 vector <llg> a[maxn],c[maxn],val[maxn]; 18 stack <llg> z; 19 20 21 inline int getint(){ 22 char c=getchar(); llg w=0,q=0; 23 while(c!='-' && ( c<'0' || c>'9')) c=getchar(); 24 if(c=='-') c=getchar(),q=1; 25 while(c>='0' && c<='9') w=w*10+c-'0',c=getchar(); 26 return q?-w:w; 27 } 28 29 void link(llg x,llg y,llg z) {a[x].push_back(y); val[x].push_back(z); val[y].push_back(z); a[y].push_back(x);} 30 31 void link_(llg x,llg y) {c[x].push_back(y); c[y].push_back(x);} 32 33 bool cmp(const node&a,const node&b){return a.df<b.df;} 34 35 void find_dad_deep(llg x,llg di) 36 { 37 bj[x]=1; dfs[x]=++cnt; dis[x]=di; 38 llg w=a[x].size(); 39 for (llg i=0;i<w;i++) 40 if (!bj[a[x][i]]) 41 { 42 dad[a[x][i]]=x; p[a[x][i]][0]=x; deep[a[x][i]]=deep[x]+1; 43 find_dad_deep(a[x][i],min(di,val[x][i])); 44 } 45 } 46 47 void build_lca() 48 { 49 for (i=1;(2<<i)<=n;i++) 50 for (j=1;j<=n;j++) 51 p[j][i]=p[p[j][i-1]][i-1]; 52 } 53 54 llg lca(llg x,llg y) 55 { 56 if (deep[x]<deep[y]) swap(x,y); 57 for (llg i=18;i>=0;i--) if (deep[p[x][i]]>=deep[y]) x=p[x][i]; 58 if (x==y) return x; 59 for (llg i=18;i>=0;i--) 60 if (p[x][i]!=p[y][i]) {x=p[x][i]; y=p[y][i];} 61 return dad[x]; 62 } 63 64 llg st[maxn],top; 65 66 void make_tree(llg x) 67 { 68 llg L=0,g1,g2; 69 while(top) 70 { 71 g1=st[top];g2=st[top-1];L=lca(g1,x); 72 if(deep[g2]>deep[L]) link_(g2,g1),top--; 73 else if(deep[g2]<deep[L]) {link_(g1,L);top--;break;} 74 else break; 75 } 76 if(st[top]!=L) st[++top]=L; 77 st[++top]=x; 78 } 79 80 void ceshi() 81 { 82 for (llg i=1;i<=n;i++) 83 { 84 llg w=c[i].size(); 85 for (llg j=0;j<w;j++) if (i<c[i][j]) cout<<i<<" "<<c[i][j]<<endl; 86 } 87 } 88 89 llg dp(llg x) 90 { 91 bj[x]=1; 92 dl[++open]=x; 93 llg w=c[x].size(),tot=0; 94 for (llg i=0;i<w;i++) 95 if (!bj[c[x][i]]) 96 tot+=dp(c[x][i]); 97 if (ss[x]) return dis[x]; 98 return min(tot,dis[x]); 99 } 100 101 int main() 102 { 103 freopen("a.in","r",stdin); freopen("a.out","w",stdout); 104 cin>>n; 105 for (i=1;i<n;i++) 106 { 107 llg x,y,z; 108 x=getint(),y=getint(),z=getint(); 109 link(x,y,z); 110 } 111 deep[1]=1; 112 llg ggg=(llg)1e60; 113 find_dad_deep(1,ggg); //dis[1]=0; 114 build_lca(); 115 cin>>T; for (i=1;i<=n;i++) bj[i]=0; 116 while (T--) 117 { 118 m=getint(); 119 llg x; 120 for (i=1;i<=open;i++) {ss[se[i]]=0; c[dl[i]].clear(); bj[dl[i]]=0;} 121 q=0,open=0; 122 c[1].clear(); bj[1]=0; ss[1]=0; 123 for (i=1;i<=m;i++) {x=getint(); d[i].po=x; d[i].df=dfs[x]; q++; ss[x]=1; se[q]=x; } 124 sort(d+1,d+m+1,cmp); 125 top=0; 126 if (d[1].po!=1) st[++top]=1; 127 for (i=1;i<=m;i++) make_tree(d[i].po); 128 while(top!=1) link_(st[top],st[top-1]),top--; 129 //if (q<=0) printf("0 "); else 130 printf("%lld ",dp(1)); 131 //ceshi(); 132 //cout<<endl; 133 } 134 return 0; 135 }