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\n",ans); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++