您的位置:首页 > 其它

bzoj 2657: [Zjoi2012]旅游(journey) (map建图+树的直径)

2016-11-02 16:29 344 查看

2657: [Zjoi2012]旅游(journey)

Time Limit: 5 Sec  Memory Limit: 128 MB

Submit: 889  Solved: 558

[Submit][Status][Discuss]

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

HINT

4<=N<=200000

Source



[Submit][Status][Discuss]


题解:map建图+树的直径

将每个三角形看做一个点,将有边相邻的点之间连边,然后求树上的最长链,即树的直径。

这样为什么是对的呢?我们是要选择两个点,求这之间经过的三角形的个数,因为是凸多边形,所以如果两个能连边,那么一定有方式让连线与三角形有至少两个公共点。

画画图就应该明白了。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#define N 1000000
#define pa pair<int,int>
using namespace std;
int tot,n,m,point
,next
,v
,f
,g
,ans;
map<pa,int> mp;
void add(int x,int y)
{
tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y;
tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x;
//	cout<<x<<" "<<y<<endl;
}
void dfs(int x,int fa)
{
int l=0,r=0; f[x]=1; g[x]=1;
for (int i=point[x];i;i=next[i])
if (v[i]!=fa){
dfs(v[i],x);
int t=f[v[i]]+1;
if (t>f[x]) g[x]=f[x],f[x]=t;
else if (t>g[x]) g[x]=t;
}
ans=max(ans,f[x]+g[x]-1);
}
int main()
{
freopen("a.in","r",stdin);
scanf("%d",&n);
for (int i=1;i<=n-2;i++) {
int x,y,z; scanf("%d%d%d",&x,&y,&z);
if (y>x) swap(y,x);
if (z>x) swap(z,x);
if (z>y) swap(y,z);
pa a=make_pair(x,y);
if (mp[a])  add(mp[a],i);
else mp[a]=i;
a=make_pair(y,z);
if (mp[a]) add(mp[a],i);
else mp[a]=i;
a=make_pair(x,z);
if (mp[a]) add(mp[a],i);
else mp[a]=i;
}
dfs(1,0);
printf("%d",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: