[BZOJ 2657] 旅游
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2657
Algorithm:
可以发现一个性质:任意两个三角形之间只可能有一种路径
任意两点只有一条路径 --------> 树
因此我们将每个三角形看成一个点,建树,找最长链即可(最后记得+1)
正好再巩固下前两天看到的1遍dfs求树直径的方法
Code:
#include <bits/stdc++.h> using namespace std; #define F first #define S second const int MAXN=2e5+10; typedef pair<int,int> P; typedef pair<P,int> PP; inline int read() { char ch;int num,f=0; while(!isdigit(ch=getchar())) f|=(ch=='-'); num=ch-'0'; while(isdigit(ch=getchar())) num=num*10+ch-'0'; return f?-num:num; } PP dat[MAXN*5]; int n,cnt=0,res=0,mx[MAXN][2]; vector<int> G[MAXN]; void Update(int a,int b,int pos){dat[++cnt]=PP(P(min(a,b),max(a,b)),pos);} void dfs(int x,int anc) { mx[x][0]=mx[x][1]=0; for(int i=0;i<G[x].size();i++) { int v=G[x][i]; if(v==anc) continue; dfs(v,x); if(mx[v][0]+1>mx[x][0]) mx[x][1]=mx[x][0],mx[x][0]=mx[v][0]+1; else if(mx[v][0]+1>mx[x][1]) mx[x][1]=mx[v][0]+1; } res=max(res,mx[x][0]+mx[x][1]); } int main() { n=read(); for(int i=1;i<=n-2;i++) { int x=read(),y=read(),z=read(); Update(x,y,i);Update(x,z,i);Update(y,z,i); //三条边参与判断 } sort(dat+1,dat+cnt+1); for(int i=1;i<=cnt-1;i++) if(dat[i].F.F==dat[i+1].F.F && dat[i].F.S==dat[i+1].F.S) G[dat[i].S].push_back(dat[i+1].S),G[dat[i+1].S].push_back(dat[i].S); dfs(1,0); cout << res+1; return 0; }
Review:
1、三角剖分建树:
将每个三角形的三条边都单独拿出来,排序,比较两两是否相等
2、任意两点只有一条路径 --------> 树
发现特殊性质,从而正确建模