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

Data Range

对于所有数据, 满足:\(4 \leq n \leq 200000\).

Explanation

任意一个凸 \(n\) 边形在三角剖分之后都会得到 \(n-2\) 个三角形.

相邻两个三角形之间有且仅有 \(1\) 条公用边, 一共有 \(n-3\) 条公用边.

于是将公用边当成两个三角形之间的边, 三角形作为新图的节点, 那么新图一定是一棵树.

经过的最多的城市的数目, 就是新图 (树) 的直径了.

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
typedef long long lli;
const int maxn = 200100;

class Graph
{
public:
    struct edge
    {
        int u, v;
        edge *next;
    };
    int n, ecnt, root;
    edge *edges[maxn], epool[maxn * 6];
    void add_edge(int u, int v)
    {
        edge *p = &epool[++ecnt],
             *q = &epool[++ecnt];
        p->u = u; p->v = v;
        p->next = edges[u]; edges[u] = p;
        q->u = v; q->v = u;
        q->next = edges[v]; edges[v] = q;
        return ;
    }
    int par[maxn], depth[maxn];
    void dfs(int p)
    {
        for (edge *ep = edges[p]; ep; ep = ep->next)
            if (ep->v != par[p]) {
                depth[ep->v] = depth[p] + 1;
                par[ep->v] = p;
                dfs(ep->v);
            }
        return ;
    }
    int get_diameter(void)
    {
        root = 1;
        depth[root] = 1;
        dfs(root);
        for (int i = 1; i <= n; i++)
            if (depth[i] > depth[root])
                root = i;
        // Calculating new depth with new root
        memset(par, 0, sizeof(par));
        memset(depth, 0, sizeof(depth));
        depth[root] = 1;
        dfs(root);
        int p = root;
        for (int i = 1; i <= n; i++)
            if (depth[i] > depth[p])
                p = i;
        return depth[p];
    }
} graph;

struct ed { int u, v, id;
    ed(void) { u = v = id = 0; }
    ed(int _1, int _2, int _3) {
        u = min(_1, _2); v = max(_1, _2); id = _3; }
    friend bool operator < (ed a, ed b) {
        if (a.u == b.u) return a.v < b.v;
        return a.u < b.u; }
} stk[maxn * 3];

int n;

int main(int argc, char** argv)
{
    scanf("%d", &n);
    int stop = 0;
    for (int i = 1, a, b, c; i <= n - 2; i++) {
        scanf("%d%d%d", &a, &b, &c);
        stk[++stop] = ed(a, b, i);
        stk[++stop] = ed(b, c, i);
        stk[++stop] = ed(c, a, i);
    }
    sort(stk + 1, stk + stop + 1);
    // Building graph to target
    graph.n = n - 2;
    for (int i = 2; i <= stop; i++)
        if (stk[i].u == stk[i-1].u && stk[i].v == stk[i-1].v)
            graph.add_edge(stk[i].id, stk[i-1].id);
    // Getting diameter for graph
    int res = graph.get_diameter();
    printf("%d\n", res);
    return 0;
}