1787: [Ahoi2008]Meet 紧急集合

Time Limit: 20 Sec  Memory Limit: 162 MB
http://www.lydsy.com/JudgeOnline/problem.php?id=1787

Description

Input

Output

Sample Input

6 4
1 2
2 3
2 4
4 5
5 6
4 5 6
6 3 1
2 4 4
6 6 6

Sample Output


5 2
2 5
4 1
6 0

HINT

Source

Day1

结论1:集合点一定在某两个点的lca上

结论2: 3个点两两算出lca,至少有2个lca相同

结论3:不同的那个lca(或3个都相同的lca)就是集合点,3个点到这个点的总距离最小

证明1:如图所示,假设等待点是 3、5、10

3个点之间的路径用蓝色标注,其余路径用橙色标注

要证明结论1,可以证明以下几点:

① 集合点 选在蓝色路径上的点 一定比 选在橙色路径上的点 更优

证明:如果集合点选在橙色路径上,即三个点可以不经过集合点到达其他点,那么选橙色路径顶端的蓝色路径上一点会更优

例如 上图中 8号点要比13号点 更优

② 集合点若选的不是lca,那么集合点越靠近lca,越优。

我们假设选的点

证明:设点a,b,c,lca为a和b的lca,设选的点d不是lca,d往lca方向移动一点,设这一点为e

那么由d向e的过程,会使①2个点的路径长度-1,另外1个点的路径长度+1   或者② 3个点的路径长度各-1

例子:①在上图中选3、5、10,集合点由4向2转移   ②在上图中好像没有。。。画一个三叉树,集合点由上往下移即可

综上可证结论1

有了结论1,就可以做这个题了,3个lca挨着算一遍即可

结论2关键点:点向上的路径有且只有唯一的一条

结论3关键点:相同的那个lca一定在另一个lca的上面

这样就可以只算那一个lca即可

然后,剩下的难以描述(语文不好),画图意会吧...

代码一:算3个lca && 倍增求lca  && 读入优化    结果:上图第3行

#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 500001
using namespace std;
int n,m,id[N],cnt,fa[N][21],p,deep[N],tmp;
int front[N],next[N*2],to[N*2],tot;
int lca1,lca2,lca3;
int read()
{int x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar();}return x;
}
void add(int x,int y)
{to[++tot]=y; next[tot]=front[x]; front[x]=tot;to[++tot]=x; next[tot]=front[y]; front[y]=tot;
}
void dfs(int x)
{id[x]=++cnt;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x][0]) {fa[to[i]][0]=x;deep[to[i]]=deep[x]+1;dfs(to[i]);}
}
int lca(int x,int y)
{if(x==y) return x;if(id[x]<id[y]) swap(x,y);for(int i=p;i>=0;i--)if(id[fa[x][i]]>id[y])x=fa[x][i];return fa[x][0];
}
int dis(int x,int y)
{int lc=lca(x,y);return deep[x]+deep[y]-2*deep[lc];
}
int main()
{n=read(); m=read();int x,y,z;for(int i=1;i<n;i++){x=read(); y=read();add(x,y);}dfs(1);p=log(n)/log(2)+1;for(int j=1;j<=p;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];int ans1,ans2,tmp;while(m--){x=read(); y=read(); z=read();lca1=lca(x,y); lca2=lca(x,z); lca3=lca(y,z);ans1=lca1; ans2=dis(x,lca1)+dis(y,lca1)+dis(z,lca1);tmp=dis(x,lca2)+dis(y,lca2)+dis(z,lca2);if(tmp<ans2) {ans2=tmp;ans1=lca2;}tmp=dis(x,lca3)+dis(y,lca3)+dis(z,lca3);if(tmp<ans2){ans2=tmp;ans1=lca3;}printf("%d %d\n",ans1,ans2);}
}

View Code

代码二:算1个lca && 倍增求lca   && 读入优化   结果: 上图第2行

#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 500001
using namespace std;
int n,m,id[N],cnt,fa[N][21],p,deep[N],tmp,ans2;
int front[N],next[N*2],to[N*2],tot;
int lca1,lca2,lca3;
int read()
{int x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar();}return x;
}
void add(int x,int y)
{to[++tot]=y; next[tot]=front[x]; front[x]=tot;to[++tot]=x; next[tot]=front[y]; front[y]=tot;
}
void dfs(int x)
{id[x]=++cnt;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x][0]) {fa[to[i]][0]=x;deep[to[i]]=deep[x]+1;dfs(to[i]);}
}
int lca(int x,int y)
{if(x==y) return x;if(id[x]<id[y]) swap(x,y);for(int i=p;i>=0;i--)if(id[fa[x][i]]>id[y])x=fa[x][i];return fa[x][0];
}
int dis(int x,int y)
{int lc=lca(x,y);return deep[x]+deep[y]-2*deep[lc];
}
int main()
{n=read(); m=read();int x,y,z;for(int i=1;i<n;i++){x=read(); y=read();add(x,y);}dfs(1);p=log(n)/log(2)+1;for(int j=1;j<=p;j++)for(int i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];while(m--){x=read(); y=read(); z=read();lca1=lca(x,y); lca2=lca(x,z); lca3=lca(y,z);if(lca1==lca2) tmp=lca3;else if(lca1==lca3) tmp=lca2;else tmp=lca1;ans2=dis(x,tmp)+dis(y,tmp)+dis(z,tmp);printf("%d %d\n",tmp,ans2);}
}

View Code

代码三:算1个lca && 树链剖分求lca && 读入优化  结果:上图第1行

#include<algorithm>
#include<cstdio>
#include<cmath>
#define N 500001
using namespace std;
int n,m,tmp,ans;
int front[N],next[N*2],to[N*2],tot;
int lca1,lca2,lca3;
int son[N],deep[N],bl[N],fa[N];
int read()
{int x=0; char c=getchar();while(c<'0'||c>'9') c=getchar();while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar();}return x;
}
void add(int x,int y)
{to[++tot]=y; next[tot]=front[x]; front[x]=tot;to[++tot]=x; next[tot]=front[y]; front[y]=tot;
}
void dfs1(int x)
{son[x]++;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x]) {fa[to[i]]=x;deep[to[i]]=deep[x]+1;dfs1(to[i]);son[x]+=son[to[i]];}
}
void dfs2(int x,int top)
{bl[x]=top;int y=0;for(int i=front[x];i;i=next[i])if(to[i]!=fa[x]&&son[to[i]]>son[y]) y=to[i];if(!y) return;dfs2(y,top);for(int i=front[x];i;i=next[i])if(to[i]!=fa[x]&&to[i]!=y) dfs2(to[i],to[i]);
}
int lca(int x,int y)
{while(bl[x]!=bl[y]){if(deep[bl[x]]<deep[bl[y]]) swap(x,y);x=fa[bl[x]];}return deep[x]<deep[y] ? x:y;
}
int dis(int x,int y)
{int lc=lca(x,y);return deep[x]+deep[y]-2*deep[lc];
}
int main()
{n=read(); m=read();int x,y,z;for(int i=1;i<n;i++){x=read(); y=read();add(x,y);}dfs1(1);dfs2(1,1);while(m--){x=read(); y=read(); z=read();lca1=lca(x,y); lca2=lca(x,z); lca3=lca(y,z);if(lca1==lca2) tmp=lca3;else if(lca1==lca3) tmp=lca2;else tmp=lca1;ans=dis(x,tmp)+dis(y,tmp)+dis(z,tmp);printf("%d %d\n",tmp,ans);}
}

View Code

上图第4行为 算3个lca && 倍增求lca

转载于:https://www.cnblogs.com/TheRoadToTheGold/p/6822268.html

[Ahoi2008]Meet 紧急集合相关推荐

  1. 1787: [Ahoi2008]Meet 紧急集合

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MB Submit: 1482  Solved: 652 [Submit ...

  2. bzoj1787 [Ahoi2008]Meet 紧急集合

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec   Memory Limit: 162 MB Submit: 2272   Solved: 1029 [ Su ...

  3. BZOJ 1787: [Ahoi2008]Meet 紧急集合

    BZOJ 1787: [Ahoi2008]Meet 紧急集合 题目描述 欢乐岛上有个非常好玩的游戏,叫做"紧急集合".在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都 ...

  4. [bzoj1787][Ahoi2008]Meet 紧急集合 倍增LCA

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec Memory Limit: 162 MB Submit: 999999999 Solved: 99999999 ...

  5. BZOJ 1787 [Ahoi2008]Meet紧急集合 题解与分析

    [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec   Memory Limit: 162 MB Description Input Output Sample Input ...

  6. BZOJ 1787 [Ahoi2008]Meet 紧急集合——LCA

    1787: [Ahoi2008]Meet 紧急集合 题目传送门 解题思路 本题是裸的LCA,特殊就在是三个点的LCA,然而并没有什么关系. 三个节点两两求LCA,将会有两个一样的公共祖先,剩下的一个就 ...

  7. [Ahoi2008] Meet 紧急集合 (LCA+倍增+rmq-st)

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit:162 MB Submit: 590  Solved: 240 [Submit][ ...

  8. bzoj 1787 bzoj 1832: [Ahoi2008]Meet 紧急集合(倍增LCA)

    1832: [AHOI2008]聚会 Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1539  Solved: 663 [Submit][Status ...

  9. BZOJ1787: [Ahoi2008]Meet 紧急集合

    [传送门:BZOJ1787] 简要题意: 给出有n个点的图,n-1条无向边,保证任意两点之间能互相到达,每条边的权值为1,给出m个询问,每个询问输入x,y,z,求出一个点使得三个点到这个点的距离和最短 ...

最新文章

  1. Nature子刊:宏基因组组装基因组实现谱系解析
  2. unity之定制脚本模板
  3. android内存优化方法,Android开发内存优化注意事项和方法
  4. IDEA overwrite报错、languagelevel设置不生效问题
  5. linux怎么用jconsole_jconsole监控linux系统的jvm使用
  6. 微信气泡主题设置_微信猫和老鼠主题怎么弄?猫和老鼠聊天气泡主题设置教程...
  7. 保护系统 用数据库加密实现数据安全
  8. admin.php c install,laravel-admin后台的安装
  9. oracle杅擂踱阀葩,Oracle常用傻瓜问题1000问
  10. vs2005 c++ mfc程序无法打开资源文件
  11. 创建与维护MySQL数据库
  12. 为什么用CDN给你网站加速?
  13. html显示网上图片不显示不出来,网页图片显示不出来,教您网页不显示图片怎么办...
  14. 大数据小项目之电视收视率企业项目01
  15. 从交互设计“流行元素”中启发
  16. 校园招聘之Offer、三方协议、两方协议、劳动合同都是什么?怎样避免被坑?...
  17. could not find included file 'pods/target support files/pods-runner/pods-runner.debug.xcconfig 什么问题
  18. Java字符串与数组的互相转换
  19. 目前流行的几种软件的压缩比较
  20. 音视频常见问题分析和解决:HLS切片丢帧引起的视频卡顿问题排查

热门文章

  1. log4j个人使用整理
  2. node.js(一)
  3. vcenter converter 转换xenserver下linux的错误
  4. 线性时间选择问题——分治
  5. 2018 react 大会_React Conf 2018的经验教训
  6. 播客#47:劳伦斯·布拉德福德
  7. yyyy-MM-dd HH:mm:ss和yyyy-MM-dd hh:mm:ss
  8. PostgreSQL 9.3 beta2 stream replication primary standby switchover bug?
  9. centos 6.4 SVN服务器多个项目的权限分组管理
  10. 连接不上ftp解决方案