消耗战

题目链接:https://www.luogu.com.cn/problem/P2495

题解:

对于单样例,可以考虑树形DP。
但此题是多实例,所以需要对树进行处理,每次询问有k+1(加上一号点)个关键点。对每个询问构造出虚树。
边权:虚树的边上的权值,为原树中两点路径上的边权最小值,可以利用倍增的思想求权值。
DP:对于虚树,设dpidp_idpi​为以iii为根的子树都与i号节点断开连接的最小代价。对于iii的每个子节点vvv,若v为关键点,则dpi+=dis(i,v)dp_i+=dis(i,v)dpi​+=dis(i,v);若v不是关键点,则dpi+=min(dis(i,v),dpv)dp_i+=min(dis(i,v), dp_v)dpi​+=min(dis(i,v),dpv​)。

#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<set>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-7using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 300100;
const int mod = 998244353;
int top, dep[maxn], fa[maxn][30], dis[maxn][30], a[maxn], vis[maxn], st[maxn];
int tot, cnt, dfn[maxn], hd1[maxn], hd2[maxn], nex[maxn*10], to[maxn*10], w[maxn*10];
void init(int n);
void Insert(int u);
LL solve(int u);
int LCA(int u, int v);
void add(int f, int t, int p, int hd[]);
void dfs(int u, int d, int f);
bool cmp(int a, int b);
int DIS(int u, int v);int main()
{tot = cnt = 1;memset(hd1, -1, sizeof(hd1));memset(hd2, -1, sizeof(hd2));int t, n, i, j, k, q, m;scanf("%d", &n);for(i=1;i<n;i++){int p;scanf("%d %d %d", &j, &k, &p);add(j, k, p, hd1);add(k, j, p, hd1);}init(n);scanf("%d", &q);while(q--){cnt = 0;scanf("%d", &m);for(i=0;i<m;i++){scanf("%d", &a[i]);vis[a[i]] = 1;}a[m++] = 1;sort(a, a+m, cmp);top = 0;for(i=0;i<m;i++)Insert(a[i]);while(top>1){add(st[top-1], st[top], DIS(st[top-1], st[top]), hd2);top--;}LL ans = solve(1);printf("%lld\n", ans);}return 0;
}bool cmp(int a, int b)
{return dfn[a]<dfn[b];
}
//构造虚树,
void Insert(int u)
{if(top == 0){st[++top] = u;return;}int lca = LCA(u, st[top]);while(top>1 && dep[lca]<dep[st[top-1]]){add(st[top-1], st[top], DIS(st[top-1], st[top]), hd2);top--;}if(dep[lca]<dep[st[top]])add(lca, st[top--], DIS(lca, st[top]), hd2);if((!top) || st[top]!=lca)st[++top] = lca;st[++top] = u;
}LL solve(int u)
{LL mi, sum = 0;for(int i=hd2[u];i!=-1;i=nex[i]){mi = solve(to[i]);if(vis[to[i]])sum += w[i];elsesum += min((LL)w[i], mi);vis[to[i]] = 0;}hd2[u] = -1;return sum;
}int DIS(int u, int v)
{if(dep[u]>dep[v])swap(u, v);int k = dep[v]-dep[u], sum = INF;for(int i=20;i>=0;i--)if((k>>i) & 1){sum = min(sum, dis[v][i]);v = fa[v][i];}return sum;
}void add(int f, int t, int p, int hd[])
{to[++cnt] = t;w[cnt] = p;nex[cnt] = hd[f];hd[f] = cnt;
}void dfs(int u, int d, int f)
{dep[u] = d;fa[u][0] = f;dfn[u] = tot++;for(int i=hd1[u];i!=-1;i=nex[i])if(to[i] != f){dfs(to[i], d+1, u);dis[to[i]][0] = w[i];}
}void init(int n)
{dfs(1, n, 0);for(int j=1;j<=22;j++)for(int i=1;i<=n;i++){fa[i][j] = fa[fa[i][j-1]][j-1];dis[i][j] = min(dis[fa[i][j-1]][j-1], dis[i][j-1]);}}int LCA(int u, int v)
{if(dep[u] > dep[v])swap(u, v);int i, j, k = dep[v]-dep[u];for(i=20;i>=0;i--)if(k&(1<<i))v = fa[v][i];if(u == v)return u;for(i=20;i>=0;i--)if(fa[u][i] != fa[v][i])v = fa[v][i], u = fa[u][i];return fa[u][0];
}

洛谷_2495 [SDOI2011]消耗战(虚树)相关推荐

  1. 洛谷 P2495 [SDOI2011]消耗战 虚树

    题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...

  2. 洛谷P2495 [SDOI2011]消耗战(虚树dp)

    P2495 [SDOI2011]消耗战 题目链接 题解: 虚树\(dp\)入门题吧.虚树的核心思想其实就是每次只保留关键点,因为关键点的dfs序的相对大小顺序和原来的树中结点dfs序的相对大小顺序都是 ...

  3. 洛谷P2495 [SDOI2011]消耗战 | 一个典型的可以搞懂虚树的例题

    题目链接 题目大意: 给出一棵树,之后对这棵树进行q次询问,每次询问一个点集,给出使得这些点集中的点都不能直接或者间接的与1相连,需要删边的最小代价(边的代价在给树的时候给出),,点集不包含1,点集总 ...

  4. 「Luogu2495」 [SDOI2011]消耗战 虚树

    Luogu P2495 [SDOI2011]消耗战 problem Solution 苦思冥想稍作思考之后可以得到一个树形DP的方法: 令\(w(u,v)\)表示u,v之间的边的权值,\(f[u]\) ...

  5. 洛谷 P2495 [SDOI2011]消耗战 题解

    题目链接 题目描述: 给你一个有边权的树,若干次询问,每次询问包含一个不含点111的kkk个点的点集,求点111与这些点都不连通的最小代价(删除一些边,代价是他们的权值和). 解题思路: 首先考虑如果 ...

  6. P2495 [SDOI2011]消耗战 虚树入门

    一棵树,n个点m个操作.每条边有权值,每个操作给你k个点,问断开若干条边后使k个点与根不相连的最小边权和是多少. 有sigmaK<500000 易知一个裸的树dp需要复杂度,m次操作后总复杂度为 ...

  7. P2495 [SDOI2011]消耗战-虚树+树形dp

    https://www.luogu.com.cn/problem/P2495 虚树:当我们在解决树形dp的问题的时候,题目中会给出一些询问,询问涉及的关键节点不多,并保证总的点数规模的时候,我们就可以 ...

  8. 洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)

    [题目链接] [思路]: 涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树. update操作时,就正常操作,难点在于query操作的计数. 因为树链剖分的dfs序只能保证一条 ...

  9. 洛谷 P2495 [SDOI2011]消耗战

    题目描述 在一场战争中,战场由n个岛屿和n-1个桥梁组成,保证每两个岛屿间有且仅有一条路径可达.现在,我军已经侦查到敌军的总部在编号为1的岛屿,而且他们已经没有足够多的能源维系战斗,我军胜利在望.已知 ...

最新文章

  1. Android UI开发第二十五篇——分享一篇自定义的 Action Bar
  2. boost::weak_ptr相关的测试程序
  3. 二叉树前序、中序和后序遍历的非递归实现
  4. 客户端实时获取Oracle数据库服务器端的系统时间
  5. linux调用堆栈函数,使用 backtrace 获得 Linux 函数调用栈
  6. python 哪些项目_一份2018年Python开源项目Top100清单!
  7. 计算机基础知识高职版,计算机应用基础 课件教学全套课件(高职版大学计算机基础 第7章 计算机网络基础知识 课件.pptx...
  8. 【VBA】用excel玩游戏,俄罗斯方块
  9. 【路由篇】02. 小米路由器通过Web接口访问硬盘文件
  10. 使用Docker-Slim对Docker镜像进行瘦身打包
  11. 深圳入户体检报告查询
  12. [转贴]汉武帝太子刘据的悲剧
  13. 容联完成1.25亿美元F轮融资
  14. [Andriod官方训练教程]管理Activity的生命活动之开始一个Activity
  15. 技术分享 | 服务端接口自动化测试, Requests 库的这些功能你了解吗?
  16. SQL DML操作之增删改查
  17. Z-BlogPHP蓝色简约风格网址收录导航网站模板
  18. Day64 Web开发6 旅游线路查询
  19. 一篇文章讲清楚交叉熵和KL散度
  20. Migrations命令小结

热门文章

  1. 并联谐振电路工作原理详解,案例+计算公式,几分钟带你搞定
  2. html页面中漂浮物怎么实现,html的section标签是什么怎么用了
  3. MTTR/MTTF/MTBF图解
  4. OA与BPM究竟有啥区别
  5. 什么密码,永远无法被黑客攻破?
  6. 页面载入-(dom、css、图片 等资源 加载完成) 执行
  7. 微信小程序-【仿咸鱼】的底部导航
  8. 跟尤雨溪一起解读Vue3源码笔记- Vue Mastery
  9. 微信小程序点击按钮弹出弹窗_微信小程序开发弹出框实现方法
  10. 2021年山东省安全员C证考试及山东省安全员C证找解析