2286: [Sdoi2011]消耗战
来源:互联网 发布:macbook绘画软件 编辑:程序博客网 时间:2024/05/29 03:33
题目链接
$题目大意:给定一棵树,边上有边权,m次询问,每次选定一些关键点,求将1号节点与所有关键点都切断所需的最小花销
同时,要求维护的信息可以方便的进行转移,这样才能在压缩信息后不影响答案
这里需要分类讨论一下,用一个栈维护一条链……
栈中的元素形成一条由根节点出发的链,初始栈中只有根节点
每次加入一个节点,求出节点与栈顶的LCA,将栈中所有深度大于LCA的节点全都弹掉
然后将LCA和该节点入栈,注意有些重复的情况要考虑
我的收获:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define L 19#define INF 1e60#define M 266666int n,k,m;int t,tot,tm,w,top;int head[M],last[M],st[M];int dfn[M],fa[M][L+2],dep[M],h[M];long long f[M],mi[M];struct edge{int to,val,nex;}e[M*4],p[M*4];//p用来存虚树 void add(int u,int v,int w){e[t]=edge{v,w,head[u]};head[u]=t++;}void ins(int u,int v){if(u==v) return ;p[tot].to=v,p[tot].nex=last[u],last[u]=tot++;} bool cmp(int x,int y){return dfn[x]<dfn[y];}void dfs(int x){ dfn[x]=++tm; for(int i=1;i<=L;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=head[x];i!=-1;i=e[i].nex){ int v=e[i].to; if(v!=fa[x][0]){ mi[v]=min(mi[x],(long long)e[i].val); fa[v][0]=x,dep[v]=dep[x]+1; dfs(v); } }}int lca(int x,int y){ if(dep[x]<dep[y]) swap(x,y); for(int i=0;i<=L;i++) if((dep[x]-dep[y])&(1<<i)) x=fa[x][i]; if(x==y) return x; for(int i=L;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0];}void dp(int x){ f[x]=mi[x]; long long tmp=0; for(int i=last[x];i!=-1;i=p[i].nex){ dp(p[i].to); tmp+=f[p[i].to]; } last[x]=-1; if(tmp&&tmp<=f[x]) f[x]=tmp;}void virtree()//http://www.cnblogs.com/owenyu/p/6724751.html{ scanf("%d",&k); for(int i=1;i<=k;i++) scanf("%d",&h[i]); sort(h+1,h+k+1,cmp);//按dfs序排序 int pts=0;tot=top=0; h[++pts]=h[1]; for(int i=2;i<=k;i++) if(lca(h[pts],h[i])!=h[pts]) h[++pts]=h[i]; st[++top]=1;//随便找一个不会成为询问点的作根 for(int i=1;i<=pts;i++){ int now=h[i],lt=lca(now,st[top]); while(dep[lt]<dep[st[top]]){ if(dep[lt]>=dep[st[top-1]]){//在两个子树,lca深度更大!! ins(lt,st[top--]); if(st[top]!=lt) st[++top]=lt; break; } ins(st[top-1],st[top]),top--; } if(st[top]!=now) st[++top]=now;//在同一子树 } while(top>1) ins(st[top-1],st[top]),top--;//剩下的 }void work(){ while(m--) { virtree(); dp(1); printf("%lld\n",f[1]); }}void init(){ int x,y,z; tot=0,memset(last,-1,sizeof(last)); t=0,memset(head,-1,sizeof(head)); scanf("%d",&n); for(int i=1;i<n;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z); mi[1]=INF;dfs(1); scanf("%d",&m);}int main(){ init(); work(); return 0;}
阅读全文
0 0
- 2286: [Sdoi2011消耗战
- 2286: [Sdoi2011消耗战
- BZOJ 2286: [Sdoi2011]消耗战
- bzoj 2286: [Sdoi2011]消耗战
- bzoj 2286: [Sdoi2011]消耗战
- 2286: [Sdoi2011]消耗战
- 2286: [Sdoi2011]消耗战
- BZOJ 2286: [Sdoi2011]消耗战
- bzoj 2286 [Sdoi2011]消耗战 虚树
- BZOJ 2286 [Sdoi2011]消耗战 虚树
- 【BZOJ】2286: [Sdoi2011消耗战【虚树DP】
- 【 bzoj 2286 】 : [Sdoi2011]消耗战 - 树形DP
- 2286: [Sdoi2011消耗战|树形DP|虚树
- bzoj 2286: [Sdoi2011消耗战 虚树+树形dp
- bzoj 2286 SDOI2011 消耗战 虚树dp
- 【BZOJ 2286】[Sdoi2011消耗战 虚树+dp
- bzoj 2286: [Sdoi2011]消耗战 虚树 DP
- 【BZOJ】2286 [Sdoi2011]消耗战 树形DP+虚树
- 系统管理员应该知道的 20 条 Linux 命令
- GAN的理解与TF的实现
- ubuntu彻底卸载mysql并且重新安装
- JDBC事务处理、提交、回滚。
- 最简单DrawerLayout侧滑菜单
- 2286: [Sdoi2011]消耗战
- vmware下虚拟机三种模式Nat,仅主机,桥接浅析
- 三分搜索--hdu3714 Error Curves
- 时间转换为ISO8061规范的UTC格式
- 心情小结 程序员的日常
- 优化的插入排序
- ffmpeg推流与播放
- 数组逆时针旋转
- HDU