博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LCA【p4281】[AHOI2008]紧急集合 / 聚会
阅读量:5260 次
发布时间:2019-06-14

本文共 2368 字,大约阅读时间需要 7 分钟。

Description

欢乐岛上有个非常好玩的游戏,叫做“紧急集合”。在岛上分散有N个等待点,有N-1条道路连接着它们,每一条道路都连接某两个等待点,且通过这些道路可以走遍所有的等待点,通过道路从一个点到另一个点要花费一个游戏币。

参加游戏的人三人一组,开始的时候,所有人员均任意分散在各个等待点上(每个点同时允许多个人等待),每个人均带有足够多的游戏币(用于支付使用道路的花费)、地图(标明等待点之间道路连接的情况)以及对话机(用于和同组的成员联系)。当集合号吹响后,每组成员之间迅速联系,了解到自己组所有成员所在的等待点后,迅速在N个等待点中确定一个集结点,组内所有成员将在该集合点集合,集合所用花费最少的组将是游戏的赢家。

小可可和他的朋友邀请你一起参加这个游戏,由你来选择集合点,聪明的你能够完成这个任务,帮助小可可赢得游戏吗?

Input

第一行两个正整数N和M(N<=500000,M<=500000),之间用一个空格隔开。分别表示等待点的个数(等待点也从1到N进行编号)和获奖所需要完成集合的次数。 随后有N-1行,每行用两个正整数A和B,之间用一个空格隔开,表示编号为A和编号为B的等待点之间有一条路。 接着还有M行,每行用三个正整数表示某次集合前小可可、小可可的朋友以及你所在等待点的编号。

Output

一共有M行,每行两个数P,C,用一个空格隔开。其中第i行表示第i次集合点选择在编号为P的等待点,集合总共的花费是C个游戏币。

我天,这题恶心坏了.

话说没出样例就敢交题的我实在是tql。 ~w~

明显到\(LCA\)处就能取到最小的值。

会需要求到\(6\)种(貌似可以求的更少.

首先这六种情况怎么算出来的.

\[ C_{3}^{2} \times 2 =6 \]

其中\(C_3^2\)代表在三个点中,随便选两个点求\(LCA\)记作\(X\)

然后再求第三个点与\(X\)\(LCA\)记作\(Y\)

注意,这里要选择\(X\)作为集合点.这样会更优.

因为走到\(Y\)的话就会是两个点对花费的贡献.这样明显更大啊.

而走到\(X\),这两个点对花费的贡献就会比较小了,另一个人多走就好了.

但是感觉不太对.但又的确是对的 emmm

比如这样:

  5bbf4d2d82cfc.png

简单来看的话,我们求出了\(b\)\(c\)\(LCA=X\)

\(a\)\(X\)\(LCA=Y\)

此时\(a,b,c\)走到\(X\)的价值为\(4\),走到\(Y\)的价值为\(5\)

(这只是一个小栗子啦 qwq)

代码

#include
#include
#include
#define R register#define N 500008using namespace std;inline void in(int &x){ int f=1;x=0;char s=getchar(); while(!isdigit(s)){if(s=='-')f=-1;s=getchar();} while(isdigit(s)){x=x*10+s-'0';s=getchar();} x*=f;}int head[N],tot,depth[N],dis[N];int n,m,gw[N][21],f[N][21];struct cod{int u,v;}edge[N<<2];inline void add(int x,int y,int z){ edge[++tot].u=head[x]; edge[tot].v=y; head[x]=tot;}void dfs(int u,int fa){ f[u][0]=fa;depth[u]=depth[fa]+1; dis[u]=dis[fa]+1; for(R int i=1;(1<
<=depth[u];i++) f[u][i]=f[f[u][i-1]][i-1]; for(R int i=head[u];i;i=edge[i].u) { if(edge[i].v==fa)continue; dfs(edge[i].v,u); }}inline int lca(int x,int y){ if(depth[x]>depth[y])swap(x,y); for(R int i=17;i>=0;i--) if(depth[x]+(1<
<=depth[y]) y=f[y][i]; if(x==y)return y; for(R int i=17;i>=0;i--) { if(f[x][i]==f[y][i])continue; x=f[x][i],y=f[y][i]; } return f[x][0];}int main(){ in(n),in(m); for(R int i=1,x,y;i
ansa)res=ansa,father=a; if(res>ansb)res=ansb,father=b; if(res>ansc)res=ansc,father=c; printf("%d %d\n",father,res); }}

转载于:https://www.cnblogs.com/-guz/p/9775076.html

你可能感兴趣的文章
day22 01 初识面向对象----简单的人狗大战小游戏
查看>>
mybatis源代码分析:深入了解mybatis延迟加载机制
查看>>
Flask三剑客
查看>>
Hibernate-缓存
查看>>
【BZOJ4516】生成魔咒(后缀自动机)
查看>>
提高PHP性能的10条建议
查看>>
svn“Previous operation has not finished; run 'cleanup' if it was interrupted“报错的解决方法...
查看>>
Java大数——a^b + b^a
查看>>
android一些细节问题
查看>>
KDESVN中commit时出现containing working copy admin area is missing错误提示
查看>>
利用AOP写2PC框架(二)
查看>>
【动态规划】skiing
查看>>
java定时器的使用(Timer)
查看>>
ef codefirst VS里修改数据表结构后更新到数据库
查看>>
boost 同步定时器
查看>>
[ROS] Chinese MOOC || Chapter-4.4 Action
查看>>
简单的数据库操作
查看>>
iOS-解决iOS8及以上设置applicationIconBadgeNumber报错的问题
查看>>
Redmine
查看>>
帧的最小长度 CSMA/CD
查看>>