zoukankan      html  css  js  c++  java
  • 题解 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 }
  • 相关阅读:
    集合框架之Map学习
    集合框架之Set学习
    解决word2016鼠标每点击一下就出现一个保存的圆圈
    装饰者模式
    IO的学习与使用
    Enumeration的学习
    在html页面中引入公共的头部和底部
    WEB-INF下资源访问问题
    给自己立一个flag
    elementui 日期选择值格式
  • 原文地址:https://www.cnblogs.com/ilverene/p/9846301.html
Copyright © 2011-2022 走看看