【题解】P2610 [ZJOI2012]旅游

link

题意

T国的国土可以用一个凸N边形来表示,包含 \(N-2\) 个城市,每个城市都是顶点为 \(N\) 边形顶点的三角形,两人的旅游路线可以看做是连接N个顶点中不相邻两点的线段。问一路能经过最多多少城市。

一个城市被当做经过当且仅当其与线路有至少两个公共点。

思路

很巧妙的一道题。(不愧是ZJOI)

三角剖分是个很有意思的信息。不是让你想递推啊喂

考虑什么样的城市是不满足三角剖分的。会发现,不可能存在一些城市围成一圈(这样有一个点就会在内部而不是端点),所以如果将相邻的城市连边,是不可能存在环的。没有环,又是连通的,那么就是树了。

问题就转化成了求树的直径,裸题。

然而事实上,建图有亿点麻烦...但是非常幸运的是,由于这道题是三角形,所以肯定是二叉树,那么我们有pair!我们有 map!我们有STL!重点是我们有O2!

于是这道题就做完了。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct edge
{
        int to,nxt;
}e[N<<1];
int head[N],tot=0,n,s[N][3],ans,g[N],f[N];
map<pair<int,int>,int> mp;

void add( int u,int v )
{
        e[++tot].to=v; e[tot].nxt=head[u]; head[u]=tot;
        e[++tot].to=u; e[tot].nxt=head[v]; head[v]=tot;
}

int dfs( int u,int fa )
{
        for ( int i=head[u]; i; i=e[i].nxt )
        {
                int v=e[i].to;
                if ( v==fa ) continue;
                int dis=dfs( v,u )+1;
                if ( f[u]<dis ) g[u]=f[u],f[u]=dis;
                else if ( g[u]<dis ) g[u]=dis;
        }
        ans=max( ans,f[u]+g[u]+1 );
        return f[u];
}

void build( int i,int j,int u )
{
        pair<int,int> pr=make_pair( i,j );
        if ( mp[pr] ) add( u,mp[pr] );
        else mp[pr]=u;
}

int main()
{
        scanf( "%d",&n );
        for ( int i=1; i<=n-2; i++ )
        {
                scanf( "%d%d%d",&s[i][0],&s[i][1],&s[i][2] ); sort( s[i],s[i]+3 ); 
                build( s[i][0],s[i][1],i ); build( s[i][1],s[i][2],i ); build( s[i][0],s[i][2],i );
        }

        dfs( 1,0 );
        printf( "%d",ans );

        return 0;
}
posted @ 2020-11-02 15:58  MontesquieuE  阅读(73)  评论(0编辑  收藏  举报