题目描述
到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~
经过一番抉择,两人决定将T国作为他们的目的地。T国的国土可以用一个凸N边形来表示,N个顶点表示N个入境/出境口。T国包含N-2个城市,每个城市都是顶点均为N边形顶点的三角形(换而言之,城市组成了关于T国的一个三角剖分)。两人的旅游路线可以看做是连接N个顶点中不相邻两点的线段。
为了能够买到最好的纪念品,小白希望旅游路线上经过的城市尽量多。作为小蓝的好友,你能帮帮小蓝吗?
输入
每个输入文件中仅包含一个测试数据。
第一行包含两个由空格隔开的正整数N,N的含义如题目所述。
接下来有N-2行,每行包含三个整数 p,q,r,表示该城市三角形的三个顶点的编号(T国的N个顶点按顺时间方向从1至n编号)。
输出
输出文件共包含1行,表示最多经过的城市数目。(一个城市被当做经过当且仅当其与线路有至少两个公共点)
样例输入
61 2 42 3 41 4 51 5 6
样例输出
4
提示
对于20%的数据,N<=2000
对于100%的数据,4<=n<=200000
思想:容易发现每个三角形最多每条边各接一个三角形,最多接三个,因此可以构造一棵树,三角形为点,三角形的边为树边,最长链就是答案。
注意题目和图形的转换思维,构造出简单的模型。
新接触了一个容器map<pair<int,int>,int>m;
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=200005;
map<pair<int,int>,int>m;
int n,a[4],ans=0,fst[maxn],cnt=0,lin[maxn],du[maxn];
bool vis[maxn];
struct data{
int u,v,next;
}e[maxn*2];
inline int get(){
char c;while(!isdigit(c=getchar()));
int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
return v;
}
inline void add(int x,int y){
e[++cnt].u=x;e[cnt].v=y;e[cnt].next=fst[x];fst[x]=cnt;++du[x];
}
inline void build(int node,int x,int y){
int p=m[make_pair(x,y)];
if(p){
add(p,node);
add(node,p);
m.erase(m.find(make_pair(x,y)));
}
else m[make_pair(x,y)]=node;
}
inline void dfs(int node){
vis[node]=1;lin[node]=1;
for(int i=fst[node];i;i=e[i].next){
int y=e[i].v;
if(vis[y])continue;
dfs(y);
ans=max(ans,lin[node]+lin[y]);
lin[node]=max(lin[node],lin[y]+1);
}
}
int main(){
n=get();memset(fst,0,sizeof(fst));
memset(vis,0,sizeof(vis));
memset(du,0,sizeof(du));
for(int i=1;i<=n-2;++i){
a[1]=get();a[2]=get(),a[3]=get();
sort(a+1,a+1+3);
build(i,a[1],a[2]);
build(i,a[2],a[3]);
build(i,a[1],a[3]);
}
dfs(1);
printf("%d\n",ans);
return 0;
}
好题