首先我们考虑每次都做一遍树形DP(树形DP自己脑补去,随便乱搞就过了)。

显然这是TLE无疑的。

由于要改变的节点个数很少,我们可以考虑用虚树重新建图,缩小范围,这样一棵树上最多有m*2个节点

然后每次对虚树进行树形dp这样总的复杂度就是n*logn的了,logn是lca的复杂度。

然后就是各种细节的地方了。。。。。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
typedef long long sint;
#define pii pair<int,int>
#define mp make_pair
#define deg 20
#define maxn 501000
#define inf 0x3f3f3f3f
#define INF (1ll<<40)
int getint()
{int res;char c;while(c=getchar(),c<'0'||c>'9');res=c-'0';while(c=getchar(),c>='0'&&c<='9')res=res*10+c-'0';return res;
}
struct node
{int u,v,next;
}tree[maxn];
int first[maxn],next[maxn],to[maxn],fa[maxn][deg];
sint dp[maxn];
int indexs,en,en2,pre[maxn],n,dfn[maxn],dep[maxn],num,T;
pii g[maxn];
int vis[maxn],meet[maxn],val[maxn],minn[maxn][deg];
void build(int a,int b,int c)
{en++;to[en]=b;val[en]=c;next[en]=first[a];first[a]=en;
}
void add(int u,int v)
{en2++;tree[en2].v=v;if(vis[u]!=T){vis[u]=T;tree[en2].next=0;}else{tree[en2].next=pre[u];}pre[u]=en2;
}
void dfs(int now)
{int v;indexs++;dfn[now]=indexs;for(int i=first[now];i;i=next[i]){v=to[i];if(v==fa[now][0]) continue;fa[v][0]=now;minn[v][0]=val[i];for(int j=1;j<deg;j++){fa[v][j]=fa[fa[v][j-1]][j-1];minn[v][j]=min(minn[v][j-1],minn[fa[v][j-1]][j-1]);}dep[v]=dep[now]+1;dfs(v);}
}
int lca(int u,int v)
{if(dep[u]<dep[v]) swap(u,v);for(int i=19;i>=0;i--){if(dep[fa[u][i]]>=dep[v])u=fa[u][i];}if(u==v)return v;for(int i=19;i>=0;i--)if(fa[u][i]!=fa[v][i]){u=fa[u][i];v=fa[v][i];}return fa[u][0];
}
int sta[maxn],top;
inline long long getmin(int x,int y)
{int ans=inf;if(dep[x]<dep[y]) swap(x,y);for(int i=19;i>=0;i--)if(dep[fa[x][i]]>=dep[y]){ans=min(ans,minn[x][i]);x=fa[x][i];}if(x==y)return ans;for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i]){ans=min(ans,min(minn[x][i],minn[y][i]));x=fa[x][i],y=fa[y][i];}if(x!=y)ans=min(ans,min(minn[x][0],minn[y][0]));return ans;
}
void dfs2(int x)
{int v;dp[x]=0;if(vis[x]==T)for(int i=pre[x];i;i=tree[i].next){dfs2(v=tree[i].v);dp[x]+=min(getmin(v,x),meet[v]==T?inf:dp[v]);}
}
void virtree()
{sta[top=1]=1;for(int i=1;i<=num;i++){int j=g[i].second;int anc=lca(sta[top],j);for(;dep[anc]<dep[sta[top]];){if(dep[sta[top-1]]<=dep[anc]){int last=sta[top--];if(sta[top]!=anc)sta[++top]=anc;add(anc,last);break;}add(sta[top-1],sta[top]),top--;}if(sta[top]!=j)sta[++top]=j;}for(;top;)add(sta[top-1],sta[top]),top--;
}
void solve()
{int a,b,c;num=getint();for(int i=1;i<=num;i++){a=getint();g[i]=mp(dfn[a],a);meet[a]=T;}sort(g+1,g+1+num);virtree();dfs2(1);printf("%lld\n",dp[1]);
}
int main()
{int a,b,c;n=getint();for(int i=1;i<n;i++){a=getint();b=getint();c=getint();build(a,b,c);build(b,a,c);}dep[1]=1;dfs(1);int cas=getint();while(cas--){T++;en2=0;solve();}return 0;
}
/*
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
*/

bzoj2286: [Sdoi2011消耗战] 虚树构造相关推荐

  1. 洛谷_2495 [SDOI2011]消耗战(虚树)

    消耗战 题目链接:https://www.luogu.com.cn/problem/P2495 题解: 对于单样例,可以考虑树形DP. 但此题是多实例,所以需要对树进行处理,每次询问有k+1(加上一号 ...

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

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

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

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

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

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

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

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

  6. BZOJ2286: [Sdoi2011]消耗战(虚树)

    BZOJ2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MB Description 在一场战争中,战场由n个岛屿和n-1个桥梁组成, ...

  7. BZOJ2286 : [Sdoi2011]消耗战

    对于每次询问,构造出虚树,相邻两点边权为该两点路径上边权的最小值 f[i]表示以i为根的子树与1不连通的最小代价,vip[i]表示i是不是关键点 f[i]=sum(vip[j]?w[j]:min(f[ ...

  8. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问, 每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接. 最少的边权和是多少. (n<=250000,sigma(ki)&l ...

  9. bzoj2286 [Sdoi2011]消耗战 单调栈+lca

    这个题意思非常明确,就是删除尽量小的边使1和指定点不连通 对于一次询问,dfs一遍即可,但需要log级别的 然后条件里有个Σ,显然复杂度和他有关,对每个点都需要一个均摊log的 然后有两个基本思路, ...

  10. P2495 [SDOI2011]消耗战

    P2495 [SDOI2011]消耗战 虚树+dpdpdp. 每次在整个图上跑dpdpdp时间肯定不够,所以考虑只对查询点和其lcalcalca进行建图. 此题的dpdpdp转移有两种方式:一种是直接 ...

最新文章

  1. python邮件发送哪个好_最全总结!聊聊 Python 发送邮件的几种方式
  2. java 基本类型 object_Java常用类-Object类
  3. ip地址管理与子网的划分二
  4. windows查看进程线程的命令pslist
  5. 嵌入式编程-C语言使用小技巧
  6. 动图-完整清晰展示TCP的三次握手与四次挥手
  7. 自己动手写游戏:飞机大战
  8. 分分钟手写http server
  9. 使用java将字符串写入到指定的文件中
  10. 2022年后人工智能/深度学习八大应用方向
  11. java 中文域名转码_转换java方法
  12. 文件从头开始读函数_如何从头开始编写自己的Promisify函数
  13. java实现人字拼,人字拼地板拼法大全
  14. 开机bat脚本解决steam无法自动登陆
  15. python使用筛选法求素数
  16. 用计算机求值根号12345,手算开根号
  17. NR接入过程中鉴权失败问题
  18. 如何卸载360安全卫士后windows系统启动项里面有360tray
  19. 什么是网络推广以及如何做好网络推广
  20. 飞机机翼的构造及其原理

热门文章

  1. Matlab高尔顿板仿真模拟实验
  2. 脑肿瘤分割论文打卡2:E1D3 U-Net for Brain Tumor Segmentation
  3. 渠道对账及差错处理系统设计
  4. cdr软件百度百科_cdr软件是什么?cdr是什么软件?
  5. 欧拉汽车,卖“萌”真能行?
  6. 2021-4-25科学计算器开高次根号
  7. 让Thinkpad USB键盘支持小红帽中键滚轮的方法(ThinkPad USB Keyboard with TrackPoint)
  8. qq音乐 android pad版,QQ音乐HD版
  9. android设置高度比例,Android View设置宽高比
  10. EXCEL函数LookUp, VLOOKUP,HLOOKUP应用详解(含中文参数解释)