[bzoj 2657] [Zjoi2012]旅游(journey)

题目在这里

考虑多边形上的每个剖出来的三角形,将每个三角形和与它相邻的三角形连边(即有两个公共点)。这样子构出来的图是一棵树。

证明:显然这个图联通,且不会出现环的情况,否则由于它是正多边形,有环的话那个中间节点一定会被若干个三角形包裹起来,那么它不可能是凸多边形的顶点。如下图:

这里写图片描述
省略号就是一堆能让它连起来的三角形,那么O点就一定不可能是凸多边形的顶点(美术天赋糟糕,勿吐槽)。

这样子的话,所谓最长的旅行路线,其实就是树上最长链了。直接两遍bfs搞定。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <ctime>
using namespace std;

const int MAXN=200005;

int n,tot,ttot,end,fst[MAXN],pre[MAXN*2],to[MAXN*2],w[MAXN],head,tail,Q[MAXN]; 
bool vis[MAXN]; 
struct Edge
{   
    int from,to,idx;
    Edge() {} Edge (int _from,int _to,int _idx) { from=_from,to=_to,idx=_idx; }
}E[MAXN*3];


bool cmp(const Edge &a,const Edge &b) { return ( (a.from<b.from) || (a.from==b.from && a.to<b.to) ); }
bool operator == (Edge a,Edge b) { return ( a.from==b.from && a.to==b.to ); } 

void E_add(int a,int b,int c,int idx)
{  
    if (a>b) swap(a,b); if (a>c) swap(a,c); if (b>c) swap(b,c); 
    E[++tot]=Edge(a,b,idx),E[++tot]=Edge(a,c,idx),E[++tot]=Edge(b,c,idx);
}

void add(int x,int y) 
{  
    pre[++ttot]=fst[x],fst[x]=ttot,to[ttot]=y;
    pre[++ttot]=fst[y],fst[y]=ttot,to[ttot]=x; 
}

int Get()
{
    char ch; int v=0; bool f=false;
    while (!isdigit(ch=getchar())) if (ch=='-') f=true; v=ch-48;
    while (isdigit(ch=getchar())) v=v*10+ch-48;
    if (f) return -v;else return v; 
}

void bfs(int S)
{   
    for (int i=1;i<=n;i++) vis[i]=false,w[i]=0; 
    head=tail=1,w[S]=1,Q[tail++]=S,vis[S]=true;
    while (head!=tail)
      { 
        int x=Q[head++];
        for (int i=fst[x];i;i=pre[i])
          {
            int y=to[i];
            if (!vis[y]) w[y]=w[x]+1,vis[y]=true,Q[tail++]=y; 
          }
      }
    end=1; 
    for (int i=2;i<=n;i++) if (w[i]>w[end]) end=i; 
}

int main()
{   
    freopen("journey.in","r",stdin);
    freopen("journey.out","w",stdout); 
    n=Get(); int a,b,c; tot=ttot=0; n-=2; 
    for (int i=1;i<=n;i++) a=Get(),b=Get(),c=Get(),E_add(a,b,c,i);

    sort(E+1,E+1+tot,cmp); 
    for (int i=1;i<=tot-1;i++) if (E[i]==E[i+1]) add(E[i].idx,E[i+1].idx);
    bfs(1); bfs(end); 
    printf("%d\n",w[end]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值