[BZOJ 2657] 旅游

Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2657

 

Algorithm:

可以发现一个性质:任意两个三角形之间只可能有一种路径

任意两点只有一条路径     -------->     树

 

因此我们将每个三角形看成一个点,建树,找最长链即可(最后记得+1)

正好再巩固下前两天看到的1遍dfs求树直径的方法

 

Code:

#include <bits/stdc++.h>

using namespace std;
#define F first
#define S second
const int MAXN=2e5+10;
typedef pair<int,int> P;
typedef pair<P,int> PP;

inline int read()
{
    char ch;int num,f=0;
    while(!isdigit(ch=getchar())) f|=(ch=='-');
    num=ch-'0';
    while(isdigit(ch=getchar())) num=num*10+ch-'0';
    return f?-num:num;
}

PP dat[MAXN*5];
int n,cnt=0,res=0,mx[MAXN][2];
vector<int> G[MAXN];

void Update(int a,int b,int pos){dat[++cnt]=PP(P(min(a,b),max(a,b)),pos);}

void dfs(int x,int anc)
{
    mx[x][0]=mx[x][1]=0;
    for(int i=0;i<G[x].size();i++)
    {
        int v=G[x][i];
        if(v==anc) continue;
        dfs(v,x);
        
        if(mx[v][0]+1>mx[x][0])
            mx[x][1]=mx[x][0],mx[x][0]=mx[v][0]+1;
        else if(mx[v][0]+1>mx[x][1])
            mx[x][1]=mx[v][0]+1;
    }
    res=max(res,mx[x][0]+mx[x][1]);
}

int main()
{
    n=read();
    for(int i=1;i<=n-2;i++)
    {
        int x=read(),y=read(),z=read();
        Update(x,y,i);Update(x,z,i);Update(y,z,i);  //三条边参与判断
    }
    
    sort(dat+1,dat+cnt+1);
    for(int i=1;i<=cnt-1;i++)
        if(dat[i].F.F==dat[i+1].F.F && dat[i].F.S==dat[i+1].F.S)
            G[dat[i].S].push_back(dat[i+1].S),G[dat[i+1].S].push_back(dat[i].S);
        
    dfs(1,0);
    cout << res+1;
    
    return 0;
}

 

Review:

1、三角剖分建树:

每个三角形的三条边都单独拿出来,排序,比较两两是否相等

 

2、任意两点只有一条路径     -------->     树

发现特殊性质,从而正确建模

posted @ 2018-05-21 15:45  NewErA  阅读(205)  评论(0编辑  收藏  举报