首页 > 代码库 > BZOJ 2657 ZJOI2012 旅游(journey) 树形DP
BZOJ 2657 ZJOI2012 旅游(journey) 树形DP
题目大意:给定一个三角剖分之后的凸多边形,求连接凸多边形的两个顶点的线段能经过的最多的三角形数
首先结论1:将相邻的三角形连边 得到的一定是一棵树
证明:如果此图出现环 那么一定有一群三角形围成一圈 那么就会在这些三角形的中间出现一些顶点 这显然是不可能的
结论2:连接两个三角形的线段经过的三角形等同于树上两个三角形路径上的所有点
证明:不会 自己画个图YY吧
总之就是相邻的三角形连边 然后O(n)搞出直径就行
连边那里偷懒用了map……
#include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 200200 using namespace std; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; int n,ans; int max_dpt[M]; map<pair<int,int>,int>e; void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void Get_Diameter(int x,int from) { int i; max_dpt[x]=1; for(i=head[x];i;i=table[i].next) { if(table[i].to==from) continue; Get_Diameter(table[i].to,x); ans=max(ans,max_dpt[x]+max_dpt[table[i].to]); max_dpt[x]=max(max_dpt[x],max_dpt[table[i].to]+1); } } void Sort(int &x,int &y,int &z) { int _x=min(min(x,y),z); int _z=max(max(x,y),z); int _y=x+y+z-_x-_z; x=_x;y=_y;z=_z; } int main() { int i,x,y,z; map<pair<int,int>,int>::iterator it; cin>>n;--n;--n; for(i=1;i<=n;i++) { scanf("%d%d%d",&x,&y,&z); Sort(x,y,z); if(it=e.find(pair<int,int>(x,y)),it!=e.end()) Add(it->second,i),Add(i,it->second),e.erase(it); else e[pair<int,int>(x,y)]=i; if(it=e.find(pair<int,int>(x,z)),it!=e.end()) Add(it->second,i),Add(i,it->second),e.erase(it); else e[pair<int,int>(x,z)]=i; if(it=e.find(pair<int,int>(y,z)),it!=e.end()) Add(it->second,i),Add(i,it->second),e.erase(it); else e[pair<int,int>(y,z)]=i; } Get_Diameter(1,0); cout<<ans<<endl; return 0; }
BZOJ 2657 ZJOI2012 旅游(journey) 树形DP
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。