首页 > 其他分享 >[POI2014] HOT-Hotels 加强版

[POI2014] HOT-Hotels 加强版

时间:2023-10-01 12:11:20浏览次数:71  
标签:le 加强版 int POI2014 son HOT hd towns dp

[POI2014] HOT-Hotels

题面翻译

给定一棵树,在树上选 \(3\) 个点,要求两两距离相等,求方案数。

题目描述

There are \(n\) towns in Byteotia, connected with only \(n-1\) roads.

Each road directly links two towns.

All the roads have the same length and are two way.

It is known that every town can be reached from every other town via a route consisting of one or more (direct-link) roads.

In other words, the road network forms a tree.

Byteasar, the king of Byteotia, wants three luxury hotels erected to attract tourists from all over the world.

The king desires that the hotels be in different towns and at the same distance one from each other.

Help the king out by writing a program that determines the number of possible locations of the hotel triplet in Byteotia.

输入格式

The first line of the standard input contains a single integer \(n\) (\(1\le n\le 10^5\)), the number of towns in Byteotia.

The towns are numbered from \(1\) to \(n\).

The Byteotian road network is then described in \(n-1\) lines.

Each line contains two integers \(a\) and \(b\) (\(1\le a\le b\le n\)) , separated by a single space, that indicate there is a direct road between the towns \(a\) and \(b\).

输出格式

The first and only line of the standard output should contain a single integer equal to the number of possible placements of the hotels.

样例 #1

样例输入 #1

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

样例输出 #1

5

最暴力的 \(O(n^2)\) 应该是枚举一个点,搜索另外两个点

但是太暴力了,没有优化空间,所以要换一种方式。

定义 \(dp_{i,j}\) 为子树 \(i\) 内,距离 \(i\) 为 \(j\) 的有多少个

然后在背包合并的时候就可以知道 lca 为 \(i\),距离为 \(j\) 的点对有多少个。

还要再选一个点,定义 \(g_{i,j}\) 为此时如果多一个距离 \(i\) 为 \(j\) 的点,答案会增加多少。合并子树时可以统计答案,顺便把 \(f\) 合并到 \(g\) 上。

#include<bits/stdc++.h>
using namespace std;
const int N=5005;
int n,fa[N],hd[N],e_num,rt;
long long f[N][N],g[N][N],ans;
struct edge{
	int v,nxt;
}e[N<<1];
void add_edge(int u,int v)
{
	e[++e_num]=(edge){v,hd[u]};
	hd[u]=e_num;
}
void dfs(int x,int y)
{
	f[x][0]++;
	for(int i=hd[x];i;i=e[i].nxt)
	{
		if(e[i].v==y)
			continue;
		dfs(e[i].v,x);
		for(int j=1;j<=n;j++)
		{
			ans+=g[x][j]*f[e[i].v][j-1];
			ans+=g[e[i].v][j+1]*f[x][j];
			g[x][j]+=f[x][j]*f[e[i].v][j-1];
			f[x][j]+=f[e[i].v][j-1];
		}
		for(int j=0;j<=n;j++)
			g[x][j]+=g[e[i].v][j+1];
	}
	ans+=g[x][0];
}
int main()
{
	scanf("%d",&n);
	for(int i=1,u,v;i<n;i++)
		scanf("%d%d",&u,&v),add_edge(u,v),add_edge(v,u);
	dfs(1,0);
	printf("%lld",ans);
}

然后发现 dp 数组的长度只和层数有关,所以可以对他进行长剖优化。

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;;
int n,fa[N],hd[N],e_num,rt,df[N],dfn[N],dp[N],son[N],idx,to[N],in[N],tme;
long g[N<<1],ans,f[N];
struct edge{
	int v,nxt;
}e[N<<1];
void add_edge(int u,int v)
{
	e[++e_num]=(edge){v,hd[u]};
	hd[u]=e_num;
}
void sou(int x,int y)
{
	for(int i=hd[x];i;i=e[i].nxt)
	{
		if(e[i].v==y)
			continue;
		sou(e[i].v,x);
		if(dp[e[i].v]>dp[son[x]])
			son[x]=e[i].v;
	}
	dp[x]=dp[son[x]]+1;
}
void suo(int x,int y)
{
	dfn[x]=++idx;
	if(son[x])
		suo(son[x],x);
	for(int i=hd[x];i;i=e[i].nxt)
	{
		if(e[i].v==y||e[i].v==son[x])
			continue;
		suo(e[i].v,x);
	}
}
void doit(int x,int y)
{
	in[x]=++idx;
	if(son[x])
		doit(son[x],x);
	for(int i=hd[x];i;i=e[i].nxt)
		if(e[i].v^son[x]&&e[i].v^y)
			idx+=dp[e[i].v],doit(e[i].v,x);
}
void dfs(int x,int y)
{
	if(son[x])
		dfs(son[x],x);
	f[dfn[x]]=1;
	for(int i=hd[x];i;i=e[i].nxt)
	{
		if(e[i].v==y||e[i].v==son[x])
			continue;
		dfs(e[i].v,x);
		for(int j=1;j<=dp[e[i].v];j++)
		{
			ans+=g[in[x]-j]*f[dfn[e[i].v]+j-1];
			if(j+1<dp[e[i].v])
				ans+=g[in[e[i].v]-j-1]*f[dfn[x]+j];
			g[in[x]-j]+=1LL*f[dfn[x]+j]*f[dfn[e[i].v]+j-1];
			f[dfn[x]+j]+=f[dfn[e[i].v]+j-1];
		}
		for(int j=0;j<dp[e[i].v]-1;j++)
			g[in[x]-j]+=g[in[e[i].v]-j-1];
	}
	ans+=g[in[x]];
}
int main()
{
	scanf("%d",&n);
	for(int i=1,u,v;i<n;i++)
		scanf("%d%d",&u,&v),add_edge(u,v),add_edge(v,u);
	sou(1,0);
	suo(1,0);
	idx=dp[1];
	doit(1,0);
	dfs(1,0);
	printf("%lld",ans);
}

标签:le,加强版,int,POI2014,son,HOT,hd,towns,dp
From: https://www.cnblogs.com/mekoszc/p/17738744.html

相关文章

  • C++的extern关键字在HotSpot VM中的重要应用
    extern关键字有两个用处:(1)extern在C/C++语言中表示函数和全局变量作用范围(可见性)的关键字,这个关键字会告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。(2)在C++中引用C语言中的函数和变量,在包含C语言头文件时,需要使用extern"C"来处理。 1、extern表示函数和变量作......
  • ​​pandas.get_dummies()​​ 是一个用于执行独热编码(One-Hot Encoding)的 pandas 函
    pandas.get_dummies()是一个用于执行独热编码(One-HotEncoding)的pandas函数。它用于将分类(或离散)特征转换为模型可以处理的二进制格式,以便更好地在机器学习算法中使用。独热编码将每个不同的类别值转换为一个新的二进制特征列,其中每个列代表一个类别,并且只有一个值为1,其余为0......
  • Mac故障排查系列:redis删除key报错MISCONF Redis is configured to save RDB snapshots
    背景:Mac下使用AnotherRedisDesktopManager客户端,删除key,遇到报错:MISCONFRedisisconfiguredtosaveRDBsnapshots,butit'scurrentlyunabletopersisttodisk.Commandsthatmaymodifythedatasetaredisabled,becausethisinstanceisconfiguredtoreporte......
  • 2023最新PS(photoshop)Win+Mac免费下载安装包及教程内置AI绘画-网盘下载
    2023最新PS(photoshop)Win+Mac免费下载安装包及教程内置AI绘画-网盘下载2023最新PS(photoshop)免费下载安装教程来咯~「PhotoShop」全套,win+mac:https://pan.quark.cn/s/9d8d8ef5c400#/list/share所有版本都有1,复制链接浏览器打开,选择一个合适的版本并下载安装包。通常情况下,建......
  • C++指针和地址偏移在HotSpot VM中的应用
     在前面我们介绍过new运算符,这个操作实际上上包含了如下3个步骤:调用operatornew的标准库函数。此函数会分配一块内存空间以便函存储相应类型的实例;调用相应类的构造函数;返回一个指向该对象的指针。在第一步中,其实我们可以自己写个operatornew函数对标准库函数进行重载,通......
  • C++ RAII在HotSpot VM中的重要应用
    RAII(ResourceAcquisitionIsInitialization),也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII的做法是使用一个对象,在其构造时获取资源,在对象生命期控制范围之下......
  • C++ RAII在HotSpot VM中的重要应用
    RAII(ResourceAcquisitionIsInitialization),也称为“资源获取就是初始化”,是C++语言的一种管理资源、避免泄漏的惯用法。C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。简单的说,RAII的做法是使用一个对象,在其构造时获取资源,在对象生命期控制范围之下......
  • AtCoder Beginner Contest 313 Ex Group Photo
    洛谷传送门AtCoder传送门考虑若重排好了\(a\),如何判断可不可行。显然只用把\(b\)排序,把\(\min(a_{i-1},a_i)\)也排序(定义\(a_0=a_{n+1}=+\infty\)),按顺序逐个判断是否大于即可。这启示我们将\(\min(a_{i-1},a_i)\)排序考虑。考虑从大到小加入\(a_i\),那么......
  • How to SupressWarnings for Sonar Security Hotspots?
    HowtoSupressWarningsforSonarSecurityHotspots?Sonarlint/SonarQubeallowsyoutousecommentsfordisablinganalysisinspecificlines.Inordertodothis,youcanjustaddacommentwiththetextNOSONARinthesameline:Randomrand=newRandom()......
  • 可替代Photoshop的开源免费软件
    Photoshop是一款功能强大的图像处理工具,但是现在的ADOBE的软件都是年付费的,就是你需要每年付费,且价格不菲,对于业余设计师、修图需求量不太高的普通用户、偶尔使用的企业用户来说,使用Photoshop的成本实在是太高,否则又容易带来侵权风险。给大家推荐几款Photoshop替代品,目标是保证设计......