偷盗钻石(Diamond)
题目描述
H国的国家博物馆最近要展出一颗巨型钻石,当然,为了防止钻石被盗,博物馆对其进行了重重保护。
H国博物馆的结构可以看成一个凸n边形,顶点编号1到n。然后通过若干面墙壁将博物馆分割成多个三角形的房间,每一道墙都会连接n边形的两个顶点。显然我们可以知道H国博物馆的房间一共有n-2个,下图为n=7是博物馆的一个平面图。
为了方便游客参观,博物馆的所有墙壁上都会有一道门(包括外墙)。游客可以通过门从一个房间来到另一个房间参观,或是进出博物馆。平时这些门都是打开着的,一旦钻石被盗,这些门就会立即锁上。著名的大盗Joker盯上了这枚巨型钻石,但是他也知道自己一旦把钻石带走,所有的门都会锁上。但这并不能难倒他,他能够打开所有门上的锁,然而开锁会消耗时间,而逃离博物馆的时间正比于开锁的总次数。为了尽快逃离,Joker会选择最优的逃离路径(他已经事先获得了博物馆的结构图)。
由于博物馆的安保人员有限,他们不能够在第一时间赶到,抓住Joker。因此他们希望将钻石摆放在尽量安全的房间中,使得Joker的逃离时间尽可能长。请你告诉馆长,Joker的逃离时间(即开锁次数)最大为多少,以方便馆长确定是否需要更多的安保人员。
输入
输入文件的第一行,包含一个正整数n,表示博物馆外墙的顶点数。
接下来的n-2行,每行三个正整数xi,yi和zi,表示每个房间的三个顶点编号。
输出
输出文件仅一行一个正整数,表示Joker的最大逃离时间。
样例输入
7 1 2 3 1 3 4 1 4 6 1 6 7 4 5 6
样例输出
2
提示
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); }