LG2610旅游
解题思路
我们考虑把这张图转换一下。
我们旅行完了一个国家后,无论我们从哪个节点出发,我们应该可以停留在任意剩下两个节点上。我们可以选择其旁边两个国家旅行。由于不能走回头路,另外一边就无法访问了。这样我们把有公共边的两个国家连边,可以构建出一张图。
我们来探究这张图有什么性质。
\(n\) 边形剖分可以得到 \(n-2\) 个三角形,\(n-3\) 表对角线。一条对角线对应一条边,一个三角对应一个点,因此这是一颗树。更进一步的,我们发现每个点度最大为 \(3\),这是一颗二叉树。
于是问题就转化为了求树的直径。两边 dfs 即可。
代码
//Don't act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you'll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
using namespace std;
int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
char read_char() {
char ch=getchar();
while(!isalpha(ch)) {
ch=getchar();
}
return ch;
}
const int MAXN=2e5+10;
int n,cnt,dis[MAXN];
int h[MAXN];
struct edge {
int v,nxt;
}e[MAXN<<1];
void addedge(int u,int v) {
e[++cnt].v=v;
e[cnt].nxt=h[u];
h[u]=cnt;
}
void insert(int u,int v) {
addedge(u,v);
addedge(v,u);
}
void dfs(int u,int fa) {
for(int i=h[u];i;i=e[i].nxt) {
int v=e[i].v;
if(v!=fa) {
dis[v]=dis[u]+1;
dfs(v,u);
}
}
}
map<int,int> mp;
int node(int x,int y) {
return x*MAXN+y;
}
void deal(int i,int a,int b) {
if(mp[node(a,b)]) {
insert(i,mp[node(a,b)]);
}
else {
mp[node(a,b)]=mp[node(b,a)]=i;
}
}
int main() {
cin>>n;
for(int i=1;i<=n-2;i++) {
int a,b,c;
a=read();b=read();c=read();
deal(i,a,b);deal(i,b,c);deal(i,c,a);
}
dfs(1,0);
int rt=0;
for(int i=1;i<=n-2;i++) {
if(dis[i]>dis[rt]) {
rt=i;
}
}
dis[rt]=1;
dfs(rt,0);
rt=0;
for(int i=1;i<=n-2;i++) {
rt=max(rt,dis[i]);
}
cout<<rt<<endl;
return 0;
}