• 偷盗钻石(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);
    }
  • 相关阅读:
    为什么button在设置标题时要用一个方法,而不像lable一样直接用一个属性
    桥接模式(透传模式)和直驱模式
    vb.net版机房收费系统——教你七层架构(三)—外观模式
    Android 4.4 KitKat NotificationManagerService使用具体解释与原理分析(二)__原理分析
    poj-2758 Checking the Text
    一种感悟,为什么努力了确还是死了一地
    一位程序员的6年总结(转)
    主键生成策略
    Linux下的crontab定时执行任务命令详解
    win7 64下安装mysql-python报错的解决办法
  • 原文地址:https://www.cnblogs.com/rrsb/p/9489555.html
Copyright © 2020-2023  润新知