bzoj 2657 旅游

Written with StackEdit.

Description

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

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

11.jpg

为了能够买到最好的纪念品,小白希望旅游路线上经过的城市尽量多。作为小蓝的好友,你能帮帮小蓝吗?

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\)

Solution

  • 将每个三角形看成一个点.相邻的两个三角形之间连边.
  • 注意到三角剖分中,一定需要剖\(N-3\)次,每剖一次,图中多出一条边,这条边只能连接一对三角形.(节点).
  • 那么这个图共有\(N-2\)个点,\(N-3\)条边,且是连通的.
  • 那么所求的答案即为树的直径.
#include<bits/stdc++.h>
using namespace std;
typedef long long LoveLive;
typedef pair<int,int> pii;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>='0'&&jp<='9')
        {
            out=out*10+jp-'0';
            jp=getchar();
        }
    return out*fh;
}
const int MAXN=2e5+10;
map<pii,int> s;
map<pii,int>::iterator it;
int n;
int cnt=0,head[MAXN];
int nx[MAXN<<1],to[MAXN<<1];
inline void add(int u,int v)
{
    ++cnt;
    to[cnt]=v;
    nx[cnt]=head[u];
    head[u]=cnt;
}
inline void ins(int u,int v)
{
    add(u,v);
    add(v,u);
}
int dep[MAXN],q[4];
void opr(int a,int b,int i)
{
    it=s.find(make_pair(q[a],q[b]));
    if(it!=s.end())
        ins(it->second,i),s.erase(it);
    else
        s[make_pair(q[a],q[b])]=i;
}
void dfs(int u,int fa)
{
    for(int i=head[u];i;i=nx[i])
        {
            int v=to[i];
            if(v==fa)
                continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
        }
}
int getd()
{
    int res=-1,rt;
    dep[1]=1;
    dfs(1,0);
    for(int i=1;i<=n-2;++i)
        if(dep[i]>res)
            res=dep[i],rt=i;
    dep[rt]=1;
    dfs(rt,0);
    for(int i=1;i<=n;++i)
        res=max(res,dep[i]);
    return res;
}
int main()
{
    n=read();
    for(int i=1;i<=n-2;++i)
        {
            q[1]=read();
            q[2]=read();
            q[3]=read();
            sort(q+1,q+4);
            opr(1,2,i);
            opr(1,3,i);
            opr(2,3,i);
        }
    int ans=getd();
    printf("%d\n",ans);
    return 0;
}

转载于:https://www.cnblogs.com/jklover/p/10054182.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值