【ZJOI2012】【BZOJ2657】旅游(journey)

Description

 到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~

经过一番抉择,两人决定将T国作为他们的目的地。T国的国土可以用一个凸N边形来表示,N个顶点表示N个入境/出境口。T国包含N-2个城市,每个城市都是顶点均为N边形顶点的三角形(换而言之,城市组成了关于T国的一个三角剖分)。两人的旅游路线可以看做是连接N个顶点中不相邻两点的线段。

这里写图片描述
为了能够买到最好的纪念品,小白希望旅游路线上经过的城市尽量多。作为小蓝的好友,你能帮帮小蓝吗?
Input
每个输入文件中仅包含一个测试数据。
第一行包含两个由空格隔开的正整数N,N的含义如题目所述。
接下来有N-2行,每行包含三个整数 p,q,r,表示该城市三角形的三个顶点的编号(T国的N个顶点按顺时间方向从1至n编号)。
Output
输出文件共包含1行,表示最多经过的城市数目。(一个城市被当做经过当且仅当其与线路有至少两个公共点)
Sample Input
6
1 2 4
2 3 4
1 4 5
1 5 6
Sample Output
4
HINT

4<=N<=200000

Source

ZJOI2012的题质量好低啊…
数列是脑残Python题,这题是傻逼最长路

把区域看成点,邻边看成连接两个点的边,因为满足图形是凸多边形,所以建出的图变成了一个树结构,然后就是找最长的一条链.
麻麻我现在也会用SPFA了我不再只会Heap-Dijkstra了QwQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define MAXN 200100
#define GET (ch>='0'&&ch<='9')
#define P 862033
using namespace std;
int n,p,q,r,top,Top;
int hash[P+1],dis[MAXN];
bool vis[MAXN];
struct edge
{
    int to;
    edge *next;
}e[MAXN<<2],*prev[MAXN];
void insert(int u,int v)
{
    e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];
}
struct Edge
{
    int u,v,id;
    bool operator <(const Edge &a)const {return u==a.u?v<a.v:u<a.u;}
}E[MAXN<<3];
void in(int &x)
{
    char ch=getchar();x=0;
    while (!GET)    ch=getchar();
    while (GET) x=x*10+ch-'0',ch=getchar();
}
void SPFA(int s)//最长路 
{
    memset(vis,0,sizeof(vis));memset(dis,-1,sizeof(dis));dis[s]=1;vis[s]=1;
    queue<int>  que;que.push(s);
    while (!que.empty())
    {
        int x=que.front();que.pop();
        for (edge *i=prev[x];i;i=i->next)
            if (dis[x]+1>dis[i->to])
            {
                dis[i->to]=dis[x]+1;
                if (!vis[i->to])
                {
                    vis[i->to]=1;
                    que.push(i->to);
                }
            }
    }
}
void Insert(int u,int v,int id)
{
    E[++Top].u=min(u,v);E[Top].v=max(u,v);E[Top].id=id;
}
int main()
{
    in(n);
    for (int i=1;i<=n-2;i++)    in(p),in(q),in(r),Insert(p,q,i),Insert(q,r,i),Insert(p,r,i);
    sort(E+1,E+Top+1);
    for (int i=2;i<=Top;i++)
        if (E[i].u==E[i-1].u&&E[i].v==E[i-1].v) insert(E[i].id,E[i-1].id),insert(E[i-1].id,E[i].id);
    SPFA(1);int x=0,maxn=0;
    for (int i=1;i<=n-2;i++)
        if (dis[i]>maxn)    maxn=dis[i],x=i;
    SPFA(x);
    for (int i=1;i<=n-2;i++)    maxn=max(maxn,dis[i]);
    printf("%d\n",maxn);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值