BZOJ-2657: [Zjoi2012]旅游(journey) (树形DP求最长链)

2657: [Zjoi2012]旅游(journey)

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 1037  Solved: 655
[ 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

两个相邻的三角形之间连边,然后求可以发现这是一棵树,求其中的最长链即可

最长链的求法值得学习,f[x]表示以x为根向下的最长链,g[x]表示以x为根向下的次长链 那么以x为最上面的点的最长链的长度就为f[x]+g[x]+1;

竟然数组开小了RE了一次 _(:зゝ∠)_ 论laj的AC率为什么还是很低 _(:зゝ∠)_

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=2e5+5;
 5 int n,f[MAX],g[MAX],ans;
 6 int tot,head[MAX],adj[MAX<<1],next[MAX<<1];
 7 struct Node{int x,y,id;}p[MAX<<2];int tx;
 8 bool cmp(Node x,Node y){return x.x==y.x?x.y<y.y:x.x<y.x;}
 9 inline int read(){
10     int an=0,x=1;char c=getchar();
11     while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();}
12     while (c>='0' && c<='9') {an=(an<<3)+(an<<1)+c-'0';c=getchar();}
13     return an*x;
14 }
15 void addedge(int u,int v){
16     tot++;adj[tot]=v,next[tot]=head[u],head[u]=tot;
17 }
18 void dfs(int x,int fa){
19     int i,j;
20     for (i=head[x];i;i=next[i]){
21         if (adj[i]==fa) continue;
22         dfs(adj[i],x);
23         if (f[x]<f[adj[i]]+1){
24             g[x]=f[x];
25             f[x]=f[adj[i]]+1;
26         }
27         else g[x]=max(g[x],f[adj[i]]+1);
28     }
29     ans=max(ans,f[x]+g[x]);
30 }
31 int main(){
32     freopen ("journey.in","r",stdin);freopen ("journey.out","w",stdout);
33     int i,j,x,y,z;
34     n=read();tot=1;
35     for (i=1;i<=n-2;i++){
36         x=read(),y=read(),z=read();
37         if (x>y) swap(x,y); if (y>z) swap(y,z); if (x>y) swap(x,y);
38         p[++tx].x=x,p[tx].y=y,p[tx].id=i;
39         p[++tx].x=x,p[tx].y=z,p[tx].id=i;
40         p[++tx].x=y,p[tx].y=z,p[tx].id=i;
41     }
42     sort(p+1,p+tx+1,cmp);
43     for (i=1;i<=tx;i++)
44         if (p[i].x==p[i-1].x && p[i].y==p[i-1].y) addedge(p[i].id,p[i-1].id),addedge(p[i-1].id,p[i].id);
45     dfs(1,0);
46     printf("%d",ans+1);
47     return 0;
48 }

 

转载于:https://www.cnblogs.com/keximeiruguo/p/7774172.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值