偷盗钻石(Diamond)

Posted rrsb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了偷盗钻石(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
",ans);
}

 

 

以上是关于偷盗钻石(Diamond)的主要内容,如果未能解决你的问题,请参考以下文章

[HG]diamond 题解

非 Diamond 类型中的虚拟继承

洛谷P3143 [USACO16OPEN]钻石收藏家Diamond Collector

洛谷 P3143 [USACO16OPEN]钻石收藏家Diamond Collector

java9新特性-8-语法改进:钻石操作符(Diamond Operator)使用升级

P3143 [USACO16OPEN]钻石收藏家Diamond Collector(伸缩法)