BZOJ2657:[ZJOI2012]旅游——题解

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

https://www.luogu.org/problemnew/show/P2610

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

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

 

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

 如果你认真想这道题就不难。

先从暴力开始想,枚举点对,找多少个三角形被它穿过。

关键问题是如何求多少个三角形被它穿过。

我们从线段的一段的三角形开始找,找它旁边的且被穿过的三角形,统计个数即可。

……等等,我们把三角形缩成了点,相邻的三角形之间连了边在跑bfs。

好的这道题就做完了,我们把三角形缩成了点,相邻的三角形之间连边找直径就是答案。

(本题卡常,测试本代码洛谷不开O2很险能过。)

#include<cstdio>
#include<cmath>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
#include<cctype>
#include<map>
using namespace std;
const int N=2e5+5;
inline int read(){
    int X=0;char ch=0;
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return X;
}
struct node{
    int to,nxt;
}e[2*N];
int head[N],cnt,n,t[N][3],ans,g[N],f[N];
map<pair<int,int>,int>mp;
inline void add(int u,int v){
    e[++cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;
    e[++cnt].to=u;e[cnt].nxt=head[v];head[v]=cnt;
}
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 d=dfs(v,u)+1;
    if(f[u]<d){
        g[u]=f[u];f[u]=d;
    }else if(g[u]<d)g[u]=d;
    }
    ans=max(ans,f[u]+g[u]+1);
    return f[u];
}
inline void make_tree(int i,int j,int u){
    pair<int,int> d=make_pair(i,j);
    if(mp[d])add(u,mp[d]);
    else mp[d]=u;
}
int main(){
    n=read();
    for(int i=1;i<=n-2;i++){
    t[i][0]=read();
    t[i][1]=read();
    t[i][2]=read();
    sort(t[i],t[i]+3);
    make_tree(t[i][0],t[i][1],i);
    make_tree(t[i][1],t[i][2],i);
    make_tree(t[i][0],t[i][2],i);
    }
    dfs(1,0);
    printf("%d
",ans);
    return 0;
}

+++++++++++++++++++++++++++++++++++++++++++

 +本文作者:luyouqi233。               +

 +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

原文地址:https://www.cnblogs.com/luyouqi233/p/8658208.html