放波建虚树的模板。

大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于lca的都弹出去。

每次做完记得复原。

还有sort的时候一定要加cmp!!!

bzoj 3611

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 1000005
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
inline int read()
{
int p=;char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')p=p*+c-'',c=getchar();
return p;
}
int n;
int dfn[N];
int fa[N][];
int dep[N],z;
int head[N],ver[N*],nxt[N*],tot;
void add(int a,int b)
{
tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;
}
void dfs(int x,int f)
{
dfn[x]=++z;
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]==f)continue;
dep[ver[i]]=dep[x]+;
fa[ver[i]][]=x;
dfs(ver[i],x);
}
return ;
}
void lca()
{
for(int i=;i<=;i++)
{
for(int j=;j<=n;j++)
{
fa[j][i]=fa[fa[j][i-]][i-];
}
}return ;
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;i--)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];y=fa[y][i];
}
}
return fa[x][];
}
bool cmp(int x,int y)
{
return dfn[x]<dfn[y];
}
int now[N],cnt;
int st[N],top;
int dian[N],num;
int vis[N];
void build()
{
tot=;
st[]=;top=;
for(int i=;i<=cnt;i++)
{
if(now[i]==)continue;
int v=now[i];
int la=lca(st[top],v);
if(st[top]!=la)
{
while(top>=&&dep[st[top-]]>dep[la])
{
add(st[top-],st[top]);top--;
}
add(la,st[top]);top--;
if(st[top]!=la)st[++top]=la;
}
st[++top]=v;
}
while(top>=)add(st[top-],st[top]),top--;
}
ll ans1;
int ans2,ans3;
int size[N];
int mx1[N],mx2[N],mn1[N],mn2[N];
void dfs(int x)
{
dian[++num]=x;
if(vis[x])size[x]=;
else size[x]=;
mx1[x]=mx2[x]=;
mn1[x]=mn2[x]=inf;
for(int i=head[x];i;i=nxt[i])
{
int quan=dep[ver[i]]-dep[x];
dfs(ver[i]);
if(vis[ver[i]])mn1[ver[i]]=;
if(mn1[ver[i]]+quan<mn1[x])
{
mn2[x]=mn1[x];
mn1[x]=mn1[ver[i]]+quan;
}
else if(mn1[ver[i]]+quan<mn2[x])mn2[x]=mn1[ver[i]]+quan;
ans1+=(long long)size[ver[i]]*(cnt-size[ver[i]])*quan;
size[x]+=size[ver[i]];
if(mx1[ver[i]]+quan>mx1[x])
{
mx2[x]=mx1[x];
mx1[x]=mx1[ver[i]]+quan;
}
else if(mx1[ver[i]]+quan>mx2[x])mx2[x]=mx1[ver[i]]+quan;
}
if(vis[x])ans2=min(ans2,mn1[x]);
else ans2=min(ans2,mn1[x]+mn2[x]);
if(mx2[x])ans3=max(ans3,mx1[x]+mx2[x]);
else if(vis[x])ans3=max(ans3,mx1[x]);
}
int main()
{
n=read();
int t1,t2,t3,t4;
for(int i=;i<n;i++)
{
t1=read();t2=read();
add(t1,t2);add(t2,t1);
}
dep[]=;
dfs(,-);
lca();
int q,k;
q=read();
memset(head,,sizeof(head));
for(int i=;i<=q;i++)
{
ans1=;ans2=inf;ans3=;
k=read();cnt=k;num=;
for(int j=;j<=k;j++)now[j]=read(),vis[now[j]]=;
sort(now+,now+k+,cmp);
build();dfs();
for(int j=;j<=cnt;j++)vis[now[j]]=;
for(int j=;j<=num;j++)head[dian[j]]=;num=;
printf("%lld %d %d\n",ans1,ans2,ans3);
}
return ;
}

bzoj2286

 #include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define N 500005
#define inf 0x3f3f3f3f
using namespace std;
int n;
int head[N],ver[N*],nxt[N*],quan[N*],tot;
inline int read()
{
int p=;char c=getchar();
while(c<''||c>'')c=getchar();
while(c>=''&&c<='')p=p*+c-'',c=getchar();
return p;
}
void add(int a,int b,int c)
{
tot++;nxt[tot]=head[a];head[a]=tot;ver[tot]=b;quan[tot]=c;
}
int fa[N][],mn[N][],dep[N];
void lca()
{
for(int i=;i<=;i++)
{
for(int j=;j<=n;j++)
{
fa[j][i]=fa[fa[j][i-]][i-];
mn[j][i]=min(mn[j][i-],mn[fa[j][i-]][i-]);
}
}
return ;
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=;i>=;i--)if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=;i>=;i--)
{
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];y=fa[y][i];
}
}
return fa[x][];
}
int z,dfn[N];
void dfs(int x,int f)
{
dfn[x]=++z;
for(int i=head[x];i;i=nxt[i])
{
if(ver[i]==f)continue;
dep[ver[i]]=dep[x]+;
fa[ver[i]][]=x;
mn[ver[i]][]=quan[i];
dfs(ver[i],x);
}return ;
}
int now[N],cnt;
int vis[N],st[N],top;
int dian[N],num;
int qur(int x,int y)
{
int ans=inf;
for(int i=;i>=;i--)
{
if(dep[fa[x][i]]>=dep[y])
{
ans=min(ans,mn[x][i]);
x=fa[x][i];
}
}
return ans;
}
void build()
{
tot=;
st[]=;top=;
for(int i=;i<=cnt;i++)
{
if(now[i]==)continue;
int v=now[i];
int la=lca(st[top],v);
if(la!=st[top])
{
while(top>=&&dep[st[top-]]>dep[la])
{
add(st[top-],st[top],qur(st[top],st[top-])),top--;
}
add(la,st[top],qur(st[top],la));top--;
if(la!=st[top])st[++top]=la;
}
st[++top]=v;
}
while(top>=)
{
add(st[top-],st[top],qur(st[top],st[top-])),top--;
}
return ;
}
long long f[N];
bool cmp(int x,int y)//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{
return dfn[x]<dfn[y];
}
void dp(int x)
{
dian[++num]=x;f[x]=;
for(int i=head[x];i;i=nxt[i])
{
dp(ver[i]);
if(vis[ver[i]])f[x]+=quan[i];
else f[x]+=min((long long)quan[i],f[ver[i]]);
}
return ;
}
int main()
{
n=read();
int t1,t2,t3,t4;
for(int i=;i<n;i++)
{
t1=read();t2=read();t3=read();
add(t1,t2,t3);add(t2,t1,t3);
}
mn[][]=inf;dep[]=;
dfs(,-);
lca();
memset(head,,sizeof(head));
int q,k;
q=read();
for(int i=;i<=q;i++)
{
k=read();cnt=k;num=;
for(int j=;j<=k;j++)
{
now[j]=read();vis[now[j]]=;
}
sort(now+,now+k+,cmp);build();
dp();
printf("%lld\n",f[]);
for(int j=;j<=k;j++)vis[now[j]]=;
for(int j=;j<=num;j++)head[dian[j]]=;
}
return ;
}

bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战的更多相关文章

  1. bzoj 3611 [Heoi2014]大工程(虚树+DP)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 408  Solved: 190[Submit][Status] ...

  2. bzoj 3611: [Heoi2014]大工程 虚树

    题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...

  3. bzoj 3611[Heoi2014]大工程 虚树+dp

    题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...

  4. bzoj 3611: [Heoi2014]大工程

    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...

  5. BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)

    题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...

  6. BZOJ 3611 [Heoi2014]大工程 ——虚树

    虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...

  7. 3611: [Heoi2014]大工程

    3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...

  8. BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程

    2286: [Sdoi2011]消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6371  Solved: 2496[Submit][Statu ...

  9. [Bzoj3611][Heoi2014]大工程(虚树)

    3611: [Heoi2014]大工程 Time Limit: 60 Sec  Memory Limit: 512 MBSubmit: 2000  Solved: 837[Submit][Status ...

随机推荐

  1. PHP中的__toString() 是什么东西

    __toString()  是魔术方法的一种,具体用途是当一个对象被当作字符串对待的时候,会触发这个魔术方法 以下说明摘自PHP官方手册 public string __toString ( void ...

  2. (转)Django配置数据库读写分离

    转:https://blog.csdn.net/Ayhan_huang/article/details/78784486 转:http://www.cnblogs.com/dreamer-fish/p ...

  3. 一个demo 理解 vuex

    相比接触vue的同学们已经看了官方文档了.这里我用一个简单的demo来阐述下vuex的知识点,虽然简单,但是容易理解.也加深自己的记忆. 用脚手架建立个项目vue init webpakc-simpl ...

  4. 20180711-统计PDB中的蛋白质种类、膜蛋白文件个数及信息等

    20180710完成这份工作.简单,但是完成了还是很开心.在我尝试如何使用pickle保存数据后,尝试保存PDB文件中“HEADER”中的信息.文件均保存于实验室服务器(97.73.198.168)/ ...

  5. Daily Scrumming* 2015.10.24(Day 5)

    一.总体情况总结 从今天开始,我们开始正式进入紧锣密鼓的集中开发周啦~~加油Fighting~ 开会讨论了一下各个人的细致分工,前端后端各自想成员分派任务. 继续各自领域的准备工作,同时开始进行开发. ...

  6. Task 10 统计从1到某个整数之间出现的1的次数

    任务:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数. 要求: 写一个函数 f(N) ,返回1 到 N 之间出现的 “1”的个数.例如 f(12) = 5. 在3 ...

  7. Gradle入门(5):创建二进制发布版本

    在创建了一个实用的应用程序之后,我们可能想将其与他人分享.其中一种方式就是创建一个可以从网站上下载的二进制文件. 这篇教程描述了如何创建一个二进制发布版本,满足以下需求: 二进制发布一定不能使用所谓的 ...

  8. 配置docker的私有仓库

    1:安装docker-registry包 yum install -y docker-distribution   2:启动docker-distribution,默认监听于TCP/5000端口 sy ...

  9. PHP 更改session存储方式为Redis

    前言: 服务器默认的session存放方式是file.当客户端发送请求带有PHPSESSID时是顺序的去比对session存储文件,如果有5000个session文件,那就有可能需要比对4998次那么 ...

  10. Excelutil 工具类

    1.说明:ExcelUtil主要用于获得单元格的数据和对对指定单元格中写入数据用! 相关代码如下: package main.java; import java.io.File; import jav ...