bzoj 3611: [Heoi2014]大工程 && bzoj 2286: [Sdoi2011消耗战
放波建虚树的模板。
大概是用一个栈维护根节点到当前关键点的一条链,把其他深度大于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消耗战的更多相关文章
- bzoj 3611 [Heoi2014]大工程(虚树+DP)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 408 Solved: 190[Submit][Status] ...
- bzoj 3611: [Heoi2014]大工程 虚树
题目: 国家有一个大工程,要给一个非常大的交通网络里建一些新的通道. 我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上. 在 2 个国家 a,b 之间建一条新通道需要的代价为树上 ...
- bzoj 3611[Heoi2014]大工程 虚树+dp
题意: 给一棵树 每次选 k 个关键点,然后在它们两两之间 新建 C(k,2)条 新通道. 求: 1.这些新通道的代价和 2.这些新通道中代价最小的是多少 3.这些新通道中代价最大的是多少 分析:较常 ...
- bzoj 3611: [Heoi2014]大工程
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...
- BZOJ.3611.[HEOI2014]大工程(虚树 树形DP)
题目链接 要求的和.最大值.最小值好像都可以通过O(n)的树形DP做,总询问点数<=2n. 于是建虚树就可以了.具体DP见DP()函数,维护三个值sum[],mx[],mn[]. sum[]要开 ...
- BZOJ 3611 [Heoi2014]大工程 ——虚树
虚树第二题.... 同BZOJ2286 #include <map> #include <cmath> #include <queue> #include < ...
- 3611: [Heoi2014]大工程
3611: [Heoi2014]大工程 链接 分析: 树形dp+虚树. 首先建立虚树,在虚树上dp. dp:sum[i]为i的子树中所有询问点之间的和.siz[i]为i的子树中有多少询问点,mn[i] ...
- BZOJ2286 [Sdoi2011]消耗战 和 BZOJ3611 [Heoi2014]大工程
2286: [Sdoi2011]消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6371 Solved: 2496[Submit][Statu ...
- [Bzoj3611][Heoi2014]大工程(虚树)
3611: [Heoi2014]大工程 Time Limit: 60 Sec Memory Limit: 512 MBSubmit: 2000 Solved: 837[Submit][Status ...
随机推荐
- tensorflow-gpu与CUDA、CUDNN的版本问题
折腾了将近两天的时间,终于搞好了,感觉把所有的坑都踩过了一遍.....泪牛满面 1.先安装CUDA,并安装,尽量不要下载最新版本的,坑,本机可以下载最新本10.0版本,但与CUDNN和tensorfl ...
- c++ 整数和字符串的转化
一.string转int的方式 采用最原始的string, 然后按照十进制的特点进行算术运算得到int,但是这种方式太麻烦,这里不介绍了. 采用标准库中atoi函数. "; int a = ...
- linux 其他知识目录
博客目录总纲首页 为博客园添加目录的方法总结 linux 命令自动补全包 手动配置网卡 nginx日志统计 Linux 深入理解inode/block/superblock /proc/sys目录下各 ...
- Redux 入门教程(一):基本用法
转自http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html(仅供个人学习使用) 首先明确一点, ...
- jQuery源码分析之整体框架
之前只是知道jQuery怎么使用,但是我觉得有必要认真的阅读一下这个库,在分析jQuery源码之前,很有必要对整个jQuery有个整体的框架概念,才能方便后面对jQuery源码的分析和学习,以下是我总 ...
- DataRow对象的RowState和DataRowVersion属性特点
DataRow对象有两个比较重要的属性,分别是行状态(RowState)和行版本(DataRowVersion),通过这两个属性能够有效的管理表中的行.下面简要的介绍一下行状态和行版本的特点和关系. ...
- No.0_Team C#
杜正远 略宅,喜昼伏夜出,却又喜游山玩水.平日多出现于宿舍食堂实验室,其他地方鲜有涉足.热爱编程与电脑游戏,渴望自己能写一款自己喜欢玩的电脑游戏,并以此为目标. 喜欢研究算法,但不喜欢硬件.正在入门软 ...
- <!CDATA[]]用法详解
所有 XML 文档中的文本均会被解析器解析. 只有 CDATA 区段(CDATA section)中的文本会被解析器忽略. PCDATA PCDATA 指的是被解析的字符数据(Parsed Chara ...
- 我的寒假C(C++)学习计划
前言 要补缺加强C语言的想法由来已久,上学期因为种种原因,某些知识点学习得不是很理想,而且,许多地方也有加强的必要,所以这次布置的随笔可谓是来得恰到好处. 学习材料 C Primer Plus 师爷的 ...
- BNUOJ 52308 We don't wanna work! set模拟
题目链接: https://acm.bnu.edu.cn/v3/problem_show.php?pid=52308 We don't wanna work! Time Limit: 60000msM ...