ssoj1232旅游

题目描述

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

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


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

输入

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

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

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

输出

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

样例输入

61 2 42 3 41 4 51 5 6

样例输出

4

提示

对于20%的数据,N<=2000


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




思想:容易发现每个三角形最多每条边各接一个三角形,最多接三个,因此可以构造一棵树,三角形为点,三角形的边为树边,最长链就是答案。
注意题目和图形的转换思维,构造出简单的模型。
新接触了一个容器map<pair<int,int>,int>m;

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=200005;
map<pair<int,int>,int>m;
int n,a[4],ans=0,fst[maxn],cnt=0,lin[maxn],du[maxn];
bool vis[maxn];
struct data{
    int u,v,next;
}e[maxn*2];
inline int get(){
    char c;while(!isdigit(c=getchar()));
    int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;
    return v;
}
inline void add(int x,int y){
    e[++cnt].u=x;e[cnt].v=y;e[cnt].next=fst[x];fst[x]=cnt;++du[x];
}
inline void build(int node,int x,int y){
    int p=m[make_pair(x,y)];
    if(p){
        add(p,node);
        add(node,p);
        m.erase(m.find(make_pair(x,y)));
    }
    else m[make_pair(x,y)]=node;
}
inline void dfs(int node){
    vis[node]=1;lin[node]=1;       
    for(int i=fst[node];i;i=e[i].next){
        int y=e[i].v;
        if(vis[y])continue;
        dfs(y);
        ans=max(ans,lin[node]+lin[y]);
        lin[node]=max(lin[node],lin[y]+1);
    }
}
int main(){
    n=get();memset(fst,0,sizeof(fst));
    memset(vis,0,sizeof(vis));
    memset(du,0,sizeof(du));
    for(int i=1;i<=n-2;++i){
        a[1]=get();a[2]=get(),a[3]=get();
        sort(a+1,a+1+3);
        build(i,a[1],a[2]);
        build(i,a[2],a[3]);
        build(i,a[1],a[3]);
    }
    dfs(1);
    printf("%d\n",ans);
    return 0;
}



好题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值