博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ2286】【SDOI2011】消耗战 [虚树][树形DP]
阅读量:5934 次
发布时间:2019-06-19

本文共 3640 字,大约阅读时间需要 12 分钟。

消耗战

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

Main idea

  给定一棵带权树,每次询问给出若干个关键节点,求出删去若干边使得关键节点无法到达根的最优方案。

Solution

  显然想到了树形DP,但是直接做DP会TLE。

  我们又发现了其实没有必要把全部边都走完,那么只要构建一棵虚树,在虚树上跑DP即可。

  虚树构建方法: 

  1. 将关键点按照DFS序排序;
  2. 求出排序后相邻两点的LCA(可以证明就是任意两点的LCA),和关键点一起按照DFS序排序,去重后得到虚树点集;
  3. 用栈扫描一遍,维护从根到当前点的链(方法:如果栈顶是i的祖先,那么连边,加入i,否则弹栈)。

Code

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 10 const int ONE=500001; 11 const int INF=2147483640; 12 13 int n,m,T; 14 int x,y,z; 15 int next1[ONE],first1[ONE],go1[ONE],w1[ONE],tot1; 16 int next[ONE],first[ONE],go[ONE],w[ONE],tot; 17 int size[250001],Rank[250001]; 18 int dfn[250001],cnt,num; 19 int f[ONE][25],Dep[250001]; 20 int Output[ONE]; 21 int N; 22 long long dp[250001]; 23 int Minedge[ONE]; 24 int vis[250001]; 25 int q[250001],top; 26 27 struct power 28 { 29 int v; 30 int rank; 31 }a[ONE]; 32 33 int cmp(const power &a,const power &b) 34 { 35 return a.rank
57) 47 if(c=='-')Q=-1; 48 if(Q) res=c-48; 49 while((c=getchar())>=48 && c<=57) 50 res=res*10+c-48; 51 return res*Q; 52 } 53 54 int Add(int u,int v,int z) 55 { 56 next1[++tot1]=first1[u]; first1[u]=tot1; go1[tot1]=v; w1[tot1]=z; 57 next1[++tot1]=first1[v]; first1[v]=tot1; go1[tot1]=u; w1[tot1]=z; 58 } 59 60 int New_Add(int u,int v,int z) 61 { 62 next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z; 63 next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=z; 64 } 65 66 int Dfs(int u,int father) 67 { 68 dfn[++cnt]=u; 69 size[u]=1; 70 Dep[u]=Dep[father]+1; 71 for(int i=0;i<=19;i++) 72 { 73 f[u][i+1]=f[f[u][i]][i]; 74 } 75 76 for(int e=first1[u];e;e=next1[e]) 77 { 78 int v=go1[e]; 79 if(v==father) continue; 80 f[v][0]=u; 81 Minedge[v]=min(w1[e],Minedge[u]); 82 Dfs(v,u); 83 size[u]+=size[v]; 84 } 85 } 86 87 int LCA(int x,int y) 88 { 89 if(Dep[x]
=0;i--) 91 { 92 if(Dep[f[x][i]]>=Dep[y]) x=f[x][i]; 93 if(x==y) return x; 94 } 95 96 for(int i=20;i>=0;i--) 97 { 98 if(f[x][i]!=f[y][i]) 99 {100 x=f[x][i];101 y=f[y][i];102 }103 }104 105 return f[x][0];106 }107 108 int Check(int u,int v)109 {110 if(Rank[u]<=Rank[v] && Rank[v]<=Rank[u]+size[u]-1) return 1; 111 return 0;112 }113 114 void Deal()115 {116 tot=0;117 for(int i=2;i<=num;i++)118 {119 int x=a[i].v;120 while(!Check(q[top],x)) top--;121 New_Add(q[top],x,Minedge[x]);122 q[++top]=x;123 }124 }125 126 void Tree_dp(int u,int father)127 {128 dp[u]=0;129 for(int e=first[u];e;e=next[e])130 {131 int v=go[e];132 if(v==father) continue;133 Tree_dp(v,u);134 if(vis[v]) dp[u]+=w[e];135 else dp[u]+=min(dp[v],(long long)w[e]);136 }137 first[u]=0;138 }139 140 int main()141 { 142 n=get();143 for(int i=1;i
View Code

 

转载于:https://www.cnblogs.com/BearChild/p/6426691.html

你可能感兴趣的文章
软件工程第二章课后练习2.5
查看>>
site url
查看>>
C# 中正则表达式 Group 分组
查看>>
vi编辑器
查看>>
Eclipse rap 富客户端开发总结(13) :Rap/Rcp保存按钮处理方式
查看>>
Diameter协议学习笔记二(常用术语)
查看>>
JavaScript概述
查看>>
(四) solr 索引数据导入 :pdf格式
查看>>
js禁止鼠标右键功能
查看>>
相邻不重复随机数的生成及优化
查看>>
VM虚拟机里的Ubuntu系统怎么设置屏幕分辨率
查看>>
使用python画一只佩奇
查看>>
kubernetes集群新增node
查看>>
C# 中的委托和事件(转)
查看>>
Java异常
查看>>
转:fragment不响应onActivityResult的问题
查看>>
【leetcode】989. Add to Array-Form of Integer
查看>>
LeetCode.922-按奇偶排序数组 II(Sort Array By Parity II)
查看>>
C#用odp.net连接Oracle 数据库
查看>>
#!/usr/bin/python3的作用 解决vscode ImportError: No module named xxxx
查看>>