• [ZJOI2012]旅游(树的直径)


    [ZJOI2012]旅游

    题目描述

    到了难得的暑假,为了庆祝小白在数学考试中取得的优异成绩,小蓝决定带小白出去旅游~~

    经过一番抉择,两人决定将T国作为他们的目的地。T国的国土可以用一个凸N边形来表示,N个顶点表示N个入境/出境口。T国包含N-2个城市,每个城市都是顶点均为N边形顶点的三角形(换而言之,[b]城市组成了关于T国的一个三角剖分[/b])。[b]两人的旅游路线可以看做是连接N个顶点中不相邻两点的线段[/b]。

    为了能够买到最好的纪念品,小白希望旅游路线上经过的城市尽量多。作为小蓝的好友,你能帮帮小蓝吗?

    输入输出格式

    输入格式:

    每个输入文件中仅包含一个测试数据。

    第一行包含两个由空格隔开的正整数N,N的含义如题目所述。

    接下来有N-2行,每行包含三个整数 p,q,r,表示该城市三角形的三个顶点的编号(T国的N个顶点按顺时间方向从1至n编号)。

    输出格式:

    输出文件共包含1行,表示最多经过的城市数目。([b]一个城市被当做经过当且仅当其与线路有至少两个公共点[/b])

    输入输出样例

    输入样例#1: 复制

    6
    1 2 4
    2 3 4
    1 4 5
    1 5 6

    输出样例#1: 复制

    4

    说明

    对于20%的数据, n<=2000

    对于100%的数据, 4<=n<=200000



    题解


    dark 水题
    这个题目就是建边难,但是你可以用map存一下,因为两个点连成的边只会有两个城市相邻。你懂的。

    不用跑spfa。
    因为一个城市最多有三个城市相邻。而最外围的城市最多两个城市相邻。三个城市相邻。父亲,左右儿子。
    直接(O(n))求直径即可。




    代码


    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<map>
    using namespace std;
    map<pair<int,int>,int >q;
    const int N=200001;
    struct node{
        int to,nex,v;
    }e[N<<2];
    int head[N],num,dis[N];
    int n,maxx,s;
    int read(){
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*w;
    }
    void add(int from,int to,int v){
        num++;
        e[num].to=to;
        e[num].v=v;
        e[num].nex=head[from];
        head[from]=num;
    }
    void dfs(int x,int fa){
        for(int i=head[x];i;i=e[i].nex){
            int v=e[i].to;if(v==fa)continue;
            dis[v]=dis[x]+e[i].v;dfs(v,x);
        }
    }
    void addx(int x,int y,int i){
        int u=q[make_pair(x,y)];
        if(u)add(i,u,1),add(u,i,1);
        else q[make_pair(x,y)]=i;
    }
    int main(){
        n=read();
        for(int i=1;i<=n-2;i++){
            int x=read(),y=read(),z=read();
            if(x>y)swap(x,y);if(x>z)swap(x,z);if(y>z)swap(y,z);
            addx(x,y,i);addx(y,z,i);addx(x,z,i);
        }
        dfs(1,0);for(int i=1;i<=n;i++){if(dis[i]>maxx)maxx=dis[i],s=i;dis[i]=0;}
        dfs(s,0);maxx=0;for(int i=1;i<=n;i++){if(dis[i]>maxx)maxx=dis[i];}
        printf("%d
    ",maxx+1);
        return 0;
    }
    
  • 相关阅读:
    BZOJ 1004: [HNOI2008]Cards [Polya 生成函数DP]
    BZOJ 1119: [POI2009]SLO [置换群]
    POJ 2154 Color [Polya 数论]
    POJ 2409 Let it Bead [置换群 Polya]
    POJ置换群入门[3/3]
    [置换群&Polya计数]【学习笔记】
    查看linux中的TCP连接数
    SIT测试 和 UAT测试
    原生app是什么意思?
    线程池原理
  • 原文地址:https://www.cnblogs.com/hhh1109/p/9525017.html
Copyright © 2020-2023  润新知