H国的国家博物馆最近要展出一颗巨型钻石,当然,为了防止钻石被盗,博物馆对其进行了重重保护。
H国博物馆的结构可以看成一个凸n边形,顶点编号1到n。然后通过若干面墙壁将博物馆分割成多个三角形的房间,每一道墙都会连接n边形的两个顶点。显然我们可以知道H国博物馆的房间一共有n-2个,下图为n=7是博物馆的一个平面图。
为了方便游客参观,博物馆的所有墙壁上都会有一道门(包括外墙)。游客可以通过门从一个房间来到另一个房间参观,或是进出博物馆。平时这些门都是打开着的,一旦钻石被盗,这些门就会立即锁上。著名的大盗Joker盯上了这枚巨型钻石,但是他也知道自己一旦把钻石带走,所有的门都会锁上。但这并不能难倒他,他能够打开所有门上的锁,然而开锁会消耗时间,而逃离博物馆的时间正比于开锁的总次数。为了尽快逃离,Joker会选择最优的逃离路径(他已经事先获得了博物馆的结构图)。
由于博物馆的安保人员有限,他们不能够在第一时间赶到,抓住Joker。因此他们希望将钻石摆放在尽量安全的房间中,使得Joker的逃离时间尽可能长。请你告诉馆长,Joker的逃离时间(即开锁次数)最大为多少,以方便馆长确定是否需要更多的安保人员。
输入文件的第一行,包含一个正整数n,表示博物馆外墙的顶点数。
接下来的n-2行,每行三个正整数xi,yi和zi,表示每个房间的三个顶点编号。
输出文件仅一行一个正整数,表示Joker的最大逃离时间。
30%数据n<=50.
60%数据n<=5000.
100%数据n<=200000.
SOL:bfs
#pragma GCC optimize("-Ofast")
#include<bits/stdc++.h>
#define pii pair<int,int>
#define eho(x) for(int i=head[x];i;i=net[i])
#define M 1000007
#define N 400007
#define v fall[i]
using namespace std;
int n,tot,p[4],fall[M],net[M],head[N],vis[N],x,ans;
queue<int> q;
map<pii,int> mp;
void read(int &x){
static char c; static int b;
for (b=1,c=getchar();!isdigit(c);c=getchar()) if (c==‘-‘) b=-1;
for (x=0;isdigit(c);c=getchar()) x=x*10+c-48;
x*=b;
}
void add(int x,int y){
// cerr<<x<<‘ ‘<<y<<endl;
fall[++tot]=y; net[tot]=head[x]; head[x]=tot;
fall[++tot]=x; net[tot]=head[y]; head[y]=tot;
}
signed main () {
read(n);
for (int i=1;i<=n-2;i++) {
read(p[0]),read(p[1]),read(p[2]);
sort(p,p+3);
if (mp.count(pii(p[0],p[1])))
add(i,mp[pii(p[0],p[1])]);
else mp[pii(p[0],p[1])]=i;
if (mp.count(pii(p[0],p[2])))
add(i,mp[pii(p[0],p[2])]);
else mp[pii(p[0],p[2])]=i;
if (mp.count(pii(p[1],p[2])))
add(i,mp[pii(p[1],p[2])]);
else mp[pii(p[1],p[2])]=i;
if (p[1]-p[0]==1) add(n+1,i);
if (p[2]-p[1]==1) add(n+1,i);
if (p[2]==n&&p[0]==1) add(n+1,i);
}
q.push(n+1);
memset(vis,127,sizeof vis);
vis[n+1]=0;
while (!q.empty()) {
x=q.front(); q.pop();
eho(x) if (vis[v]>vis[x]+1) {
vis[v]=vis[x]+1,q.push(v);
if (vis[v]>ans) ans=vis[v];}
}
printf("%d\n",ans);
}