【校内模拟】Polygon(结论)(树形DP)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/zxyoi_dreamer/article/details/102725673

简要题意:

给你一个凸多边形,并且给你一个三角剖分,请你找一个以这个凸多边形顶点为顶点的三角形,使得在给出的三角剖分中,被你找的三角形覆盖的三角形尽可能多。这里并不要求完全覆盖,只要交的面积不为0即可。

题解:

由于数据范围不大(出题人懒得写数据生成器造不了强的数据),考场上写的 O ( n 2 log n ) O(n^2\log n) 的过了,但是这道题可以做到 O ( n ) O(n)

将所有三角形建点,有公共边的三角形之间连边,显然是一个树形结构。

这个结构上任意两点之间的简单路径穿过的边,在原来的凸多边形中都可以用一条直线来全部穿过。

并且两片叶子之间的路径唯一对应着原图的一条对角线。

所以三角形在转化后的图里面对应的就是三叉路径,求出最长的三叉路径用树形DP即可。


代码:

#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const

cs int N=1e3+7;

int n,ans;

int el[N],nxt[N<<1],to[N<<1],ec;
inline void adde(int u,int v){
	nxt[++ec]=el[u],el[u]=ec,to[ec]=v;
	nxt[++ec]=el[v],el[v]=ec,to[ec]=u;
}

std::unordered_map<int,int> id;

int d[N];
void dfs1(int u,int p){
	for(int re e=el[u],v=to[e];e;v=to[e=nxt[e]])
	if(v!=p)dfs1(v,u),d[u]=std::max(d[u],d[v]);++d[u];
}

void dfs2(int u,int p,int out){
	int mx[2]={0,0};
	for(int re e=el[u],v=to[e];e;v=to[e=nxt[e]])
	if(v!=p){
		if(d[v]>mx[1])mx[0]=mx[1],mx[1]=d[v];
		else if(d[v]>mx[0])mx[0]=d[v];
	}
	ans=std::max(ans,out+1+mx[0]+mx[1]);
	for(int re e=el[u],v=to[e];e;v=to[e=nxt[e]])
	if(v!=p)dfs2(v,u,1+std::max(out,d[v]==mx[1]?mx[0]:mx[1]));
}

signed main(){
#ifdef zxyoi
	freopen("polygon.in","r",stdin);
#endif
	scanf("%d",&n);
	for(int re i=1;i<=n-2;++i){int a[3];
		for(int re j=0;j<3;++j)scanf("%d",a+j);
		std::sort(a,a+3);
		for(int re j=0;j<2;++j)
		for(int re k=j+1;k<3;++k)
		if(id[a[j]*N+a[k]])adde(i,id[a[j]*N+a[k]]);
		for(int re j=0;j<2;++j)
		for(int re k=j+1;k<3;++k)id[a[j]*N+a[k]]=i;
	}
	dfs1(1,0);
	dfs2(1,0,0);
	std::cout<<ans<<"\n";
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/102725673