[ZJOI2012] 旅游

题目描述

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

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

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

输入输出格式

输入格式:

每个输入文件中仅包含一个测试数据。

第一行包含两个由空格隔开的正整数N,N的含义如题目所述。

接下来有N-2行,每行包含三个整数 p,q,r,表示该城市三角形的三个顶点的编号(T国的N个顶点按顺时间方向从1至n编号)。

输出格式:

输出文件共包含1行,表示最多经过的城市数目。([b]一个城市被当做经过当且仅当其与线路有至少两个公共点[/b])

输入输出样例

输入样例#1: 复制

6
1 2 4
2 3 4
1 4 5
1 5 6

输出样例#1: 复制

4

说明

对于20%的数据, n<=2000
对于100%的数据, 4<=n<=200000

Solution

一句话题意,三个边围成一个城市,拥有共同边的城市可以互相到达。
显然,这个图可以建成一棵树,拥有共同城市的建边,用map存下,这条边有没有出现过,求树上最长路,树的直径,没了,一道水题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
typedef pair<int,int> pr;
map<pr,int> q;
struct node
{
    int to,next,w;
}a[2001010];
int len,last[501010],d[501000];
void add(int a1,int a2,int a3)
{
    a[++len].to=a2;
    a[len].w=a3;
    a[len].next=last[a1];
    last[a1]=len;
}
void dfs(int x,int father)
{
    for(int i=last[x];i;i=a[i].next)
    {
        int to=a[i].to;
        if(to==father) continue;
        d[to]=d[x]+a[i].w;
        dfs(to,x);
    }
}
int main()
{
    int n,x,y,z;
    cin>>n;
    for(int i=1;i<=n-2;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        if(x>y) swap(x,y);
        if(y>z) swap(y,z);
        if(x>y) swap(x,y);
        int s=q[pr(x,y)];
        if(s) add(i,s,1),add(s,i,1);
        else q[pr(x,y)]=i;
        s=q[pr(x,z)];
        if(s) add(i,s,1),add(s,i,1);
        else q[pr(x,z)]=i;
        s=q[pr(y,z)];
        if(s) add(i,s,1),add(s,i,1);
        else q[pr(y,z)]=i;
    }
    dfs(1,0);
    int l=0,r=0;
    for(int i=1;i<=n;i++) if(d[i]>d[l]) l=i;
    memset(d,0,sizeof(d));
    dfs(l,0);
    for(int i=1;i<=n;i++) if(d[i]>d[r]) r=i;
    cout<<d[r]+1<<endl;
}

博主蒟蒻,可以随意转载,但必须附上原文链接k-z-j

posted @ 2018-08-20 19:43  k-z-j  阅读(294)  评论(0编辑  收藏  举报