题解 P2610 【[ZJOI2012]旅游】

今天模拟赛考了这道题,那就来水一篇题解吧。。。(话说提高组模拟赛考什么省选题啊??)


 

这道题要我们求一条线段最多能经过的三角形数量。

回想小学学过的奥数,老师告诉过我们这样一件事:`点无大小 线无粗细`。

既然如此,为什么不能把这条线段看成一条巨大的把三角形看成点呢?

那么本题的思路就出来了:我们把三角形看成点,然后建立一颗二叉树,在树上跑两边BFS求直径就可以了。

可是为什么我们一定能建成二叉树呢?

其实很好证明。

三角形只有三条边,那么最多能有一个父亲和两个儿子,所以是二叉树。

当然,这个东西不是特别重要。

重点是,我们接下来怎么建图?

这里我是这样解决的:

先把每一条边都存进一个map里面,然后map手写结构体统计边出现的次数。

然后遍历一遍map,把所有出现不止一次的边两端的三角形连在一起。

这个办法唯一的问题是常数比较大,写的丑就容易TLE(然而机房的lemon竟然可以AC!)。


 

AC代码如下:

955ms 38272kb

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 namespace StandardIO{
 6 
 7     template<typename T>inline void read(T &x){
 8         x=0;T f=1;char c=getchar();
 9         for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
10         for(;c>='0'&&c<='9';c=getchar())x=x*10+c-'0';
11         x*=f;
12     }
13 
14     template<typename T>inline void write(T x){
15         if(x<0)putchar('-'),x*=-1;
16         if(x>=10)write(x/10);
17         putchar(x%10+'0');
18     }
19 
20 }
21 
22 using namespace StandardIO;
23 
24 namespace Solve{
25 
26     const int N=200001;
27 
28     int n;
29     struct __normal_pair{   
30         int first,second;
31         inline bool operator < (const __normal_pair &x)const{
32             if(first==x.first)return second<x.second;
33             return first<x.first;
34         }
35     };  
36     struct __store_pair{
37         int first,second,size;
38         inline void push_back(int id){
39             if(size++)second=id;
40             else first=id;
41         }
42     };
43     map<__normal_pair,__store_pair>edge;
44     vector<int>graph[N];
45     int dis[N],vis[N];
46 
47     inline __normal_pair make_pair(int f,int s){
48         return (__normal_pair){f,s};
49     }
50     inline void sor(int &a,int &b,int &c){
51         if(a>b)swap(a,b);
52         if(a>c)swap(a,c);
53         if(b>c)swap(b,c);
54     }
55     inline int bfs(int s,int time){
56         queue<int>q;
57         dis[s]=0,vis[s]=time;
58         q.push(s);
59         int final;
60         while(!q.empty()){
61             final=q.front();q.pop();
62             for(register vector<int>::iterator i=graph[final].begin();i!=graph[final].end();++i){
63                 if(vis[*i]==time)continue;
64                 vis[*i]=time,dis[*i]=dis[final]+1;
65                 q.push(*i);
66             }
67         }
68         return final;
69     }
70 
71     inline void solve(){
72         read(n);
73         for(register int i=1;i<=n-2;++i){
74             int p,q,r;
75             read(p),read(q),read(r);
76             sor(p,q,r);
77             edge[make_pair(p,q)].push_back(i);
78             edge[make_pair(q,r)].push_back(i);
79             edge[make_pair(p,r)].push_back(i);
80         }
81         for(register map<__normal_pair,__store_pair>::iterator i=edge.begin();i!=edge.end();++i){
82             if(i->second.size>1){
83                 graph[i->second.first].push_back(i->second.second);
84                 graph[i->second.second].push_back(i->second.first);
85             }
86         }
87         write(dis[bfs(bfs(1,1),2)]+1);
88     }
89 
90 }
91 
92 using namespace Solve;
93 
94 int main(){
95 //    freopen("triangulation9.in","r",stdin);
96 //    freopen("triangulation.out","w",stdout);
97     solve();
98 }

 

posted @ 2018-10-24 21:32  Ilverene  阅读(363)  评论(0编辑  收藏  举报