LG2610旅游(dfs)

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;
}


posted @ 2022-04-02 10:01  huayucaiji  阅读(20)  评论(0编辑  收藏  举报