BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】
2286: [Sdoi2011]消耗战
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 4261 Solved: 1552
[Submit][Status][Discuss]
Description
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
Sample Output
HINT
对于100%的数据,2<=n<=250000,m>=1,sigma(ki)<=500000,1<=ki<=n-1
我一定要吐槽一下,神™c <= 100000,假的吧= =
我INF开了10^9都不够和c比,调了一中午对别人代码从头对到尾就是找不出错= =
MMP
唉,还是自己弱,刚学虚树,对建树过程不太自信
先说说树形dp,我们设f[i]表示i节点封锁的最小开销【我们把每条向上的边直接看做该点的权值】
则f[i] = min(v[i],∑f[to])
我们知道封锁父亲效果一定不比封锁儿子差,那么每个点u的权值可以看做v[u] = min(v[u的祖先们])、
直接做肯定T,O(mn),题目甚至直接都没有m的上限,而k的上限提醒我们只处理每次涉及到的点
如何抽出一棵树中单独的一些点呢?这就是虚树了
虚树
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
#define PP(a,b) printf("link %d -> %d\n",a,b)
using namespace std;
const int maxn = 250005,maxm = 510005;
const LL INF = 100000000000000000ll;
inline int RD(){int out = 0,flag = 1; char c = getchar();while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}return out * flag;
}
int n,m,K,h[maxn],ne = 0,fa[maxn][20],dfn[maxn],dep[maxn],cnt = 0;
int s[maxn],t[maxn];
LL mn[maxn],f[maxn];
struct EDGE{int to,nxt; LL w;}ed[maxm];
inline void build(int u,int v,int w){ed[ne] = (EDGE){v,h[u],w}; h[u] = ne++;ed[ne] = (EDGE){u,h[v],w}; h[v] = ne++;
}
inline void add(int u,int v){if (u != v) {ed[ne] = (EDGE){v,h[u],0}; h[u] = ne++;}}
void dfs(int u,int ff,int d){fa[u][0] = ff; dfn[u] = ++cnt; dep[u] = ++d;Redge(u) if (ed[k].to != ff){mn[ed[k].to] = min(mn[u],ed[k].w);dfs(ed[k].to,u,d);}
}
void init(){REP(j,19) REP(i,n) fa[i][j] = fa[fa[i][j - 1]][j - 1];}
int lca(int u,int v){if (dep[u] < dep[v]) swap(u,v);int d = dep[u] - dep[v];for (int i = 0; (1 << i) <= d; i++)if (d & (1 << i)) u = fa[u][i];for (int i = 19; i >= 0; i--)if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];if (u == v) return u;return fa[u][0];
}
inline bool cmp(const int& a,const int& b){return dfn[a] < dfn[b];}
void rebuild(){int top,tot = 0; s[top = 1] = 1; ne = 0;sort(t + 1,t + 1 + K,cmp); t[++tot] = t[1];for (int i = 2 ; i <= K; i++) if (lca(t[i],t[tot]) != t[tot]) t[++tot] = t[i];for (int i = 1; i <= tot; i++){int u = t[i],v = lca(u,s[top]);while (true){if (dep[v] >= dep[s[top - 1]]){add(v,s[top--]); if (v != s[top]) s[++top] = v;break;}add(s[top - 1],s[top]); top--;}if (s[top] != u) s[++top] = u;}while (--top) add(s[top],s[top + 1]);
}
void dp(int u){f[u] = mn[u]; LL tmp = 0;Redge(u) dp(ed[k].to),tmp += f[ed[k].to];h[u] = -1;if (tmp == 0) f[u] = mn[u];else if (tmp <= f[u]) f[u] = tmp;
}
void solve(){K = RD(); REP(i,K) t[i] = RD();rebuild(); dp(1);printf("%lld\n",f[1]);
}
int main(){memset(h,-1,sizeof(h));n = RD(); int a,b,w;for (int i = 1; i < n; i++) a = RD(),b = RD(),w = RD(),build(a,b,w);mn[1] = INF; dfs(1,0,0); init();REP(i,n) h[i] = -1;m = RD(); while (m--) solve();return 0;
}
转载于:https://www.cnblogs.com/Mychael/p/8282760.html
BZOJ2286 [Sdoi2011]消耗战 【虚树 + 树形Dp】相关推荐
- P2495 [SDOI2011]消耗战-虚树+树形dp
https://www.luogu.com.cn/problem/P2495 虚树:当我们在解决树形dp的问题的时候,题目中会给出一些询问,询问涉及的关键节点不多,并保证总的点数规模的时候,我们就可以 ...
- BZOJ 2286 消耗战 (虚树+树形DP)
给出一个n节点的无向树,每条边都有一个边权,给出m个询问, 每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接. 最少的边权和是多少. (n<=250000,sigma(ki)&l ...
- [WC2018]通道——边分治+虚树+树形DP
题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...
- BZOJ5341[Ctsc2018]暴力写挂——边分治+虚树+树形DP
题目链接: CSTC2018暴力写挂 题目大意:给出n个点结构不同的两棵树,边有边权(有负权边及0边),要求找到一个点对(a,b)满足dep(a)+dep(b)-dep(lca)-dep'(lca)最 ...
- 「Luogu2495」 [SDOI2011]消耗战 虚树
Luogu P2495 [SDOI2011]消耗战 problem Solution 苦思冥想稍作思考之后可以得到一个树形DP的方法: 令\(w(u,v)\)表示u,v之间的边的权值,\(f[u]\) ...
- 洛谷_2495 [SDOI2011]消耗战(虚树)
消耗战 题目链接:https://www.luogu.com.cn/problem/P2495 题解: 对于单样例,可以考虑树形DP. 但此题是多实例,所以需要对树进行处理,每次询问有k+1(加上一号 ...
- BZOJ5419[Noi2018]情报中心——线段树合并+虚树+树形DP
题目链接: [NOI2018]情报中心 题目大意:给出一棵n个节点的树,边有非负边权,并给出m条链,对于每条链有一个代价,要求选出两条有公共边的链使两条链的并的边权和-两条链的代价和最大. 花了一天的 ...
- bzoj 3611: [Heoi2014]大工程(虚树+树形DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MB Submit: 1697 Solved: 718 [Submit][Stat ...
- 洛谷 P2495 [SDOI2011]消耗战 虚树
题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...
- BZOJ 3611 [Heoi2014]:虚树+树形DP
时空隧道 今天考试T3正解是虚树-..(看到这个名字我好虚啊-.) 现在我们需要处理一棵树上k个点的询问,做一遍树形DP-- 复杂度是O(n)的,q个询问,感觉复杂度很爆炸-..>_<-- ...
最新文章
- 百万奖金 !「悟道之巅」AI创新应用大赛,开幕!
- 物联网通信协议全解析
- bootsrap+jquery+组件项目引入文件的常见报错
- 编写简单的UDP应用
- P4841,jzoj3303-城市规划【NTT,多项式求逆,dp】
- iproute2 对决 net-tools
- Android Message和obtainMessage的区别
- Julia : 1亿条记录读取测试,及几个优化点
- 激光通信的优点与缺点
- ele-ui表单验证规则中的手机号码和邮箱的验证规则
- VT100 终端控制码
- 网红漏洞“致远OA系统上的GetShell漏洞”详解
- ffmpeg 常用命令总结:(avi转MP4、MP4转ts、视频压缩、去除视频声音、合并音频和视频)
- 微型计算机输出设备 写出六种,2017计算机一级考试强化训练
- UITT不忘初心,为交易而生
- ”AE-OT A NEW GENERATIVE MODEL BASED ON EXTENDED“阅读笔记
- 当当网商品详情API接口(当当商品详情接口,当当商品评论接口,当当商品问答接口,当当抢购价接口,当当商品列表接口)代码对接教程
- gaussdb 【FAQ_002】【gs_guc配置pg_hba.conf后不生效】
- 奇葩公司规定程序员工资按代码行数算工资,个个提成这么高?
- 【大数据存储技术】第7章 MongoDB 的原理和使用
热门文章
- The Top 8 Security and Risk Trends We’re Watching
- MPLS virtual private network PE-CE之间的路由协议(静态、RIP、IS-IS)
- C++ 实数和二进制操作入门
- linux系统中命令执行的优先级以及命令格式
- php 获取TZ时间格式
- zabbix+ldap认证故障解决一例
- fcm模糊聚类matlab实例_智能控制-Fuzzy控制- matlab
- xsd文件转图片_原来华为手机能一键将图片转为PDF,实在太方便啦!你还不会吗?...
- gps导航计算机毕业设计开题报告,GPS导航计算机毕业设计开题报告.doc
- 查找 --- Search Insert Position --- 图解