zoukankan      html  css  js  c++  java
  • [洛谷P2610] [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

    一句话题意: 给出一个 奇奇怪怪的(??) 多边形,其中每(3)条边围成一个城市,每两个相连的城市中有一条边,问从任意一个城市出发不重复经过某个城市最多能经过多少个城市.

    题解: 首先对于这种奇奇怪怪的题目,我们需要将它转化模型.很显然这个连通关系可以将它转化成一个图论问题.对于这个建边,有一点小技巧,比如我们发现一条边只会连通两个城市,并且一条边一定是由多边形上的两个顶点确定的.所以我们可以将一条边的两个顶点的存入一个结构体内,并用(map)记录第一次与这条边接触的城市是哪一个.这样如果遍历到一个有值的边,就可以直接建边了.

    然后我们需要思考这个建出来的图都有些什么性质.一个城市是一个三角形,那么显然它最多与三个城市连边,并且在边界上的城市是不会有三个城市与它相连的.并且在图中不会存在环,也就是两个三角形不可能有超过一条边的公共边.

    那么知道这些性质了,我们就会发现它是一棵树,并且如果以边界为根的话,它还是一颗二叉树.

    在树上找一条最长的路径,显然就是求树的直径,直接跑一遍(dfs)求出直径就可以了.

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 200000+5;
    
    int n, ecnt = 0, last[N], ans = 0, f[N];
    
    struct edge{
        int to, nex, w;
    }e[N*2];
    
    struct line{
        int x, y;
        bool operator < (const line &a) const{
            return x == a.x ? y < a.y : x < a.x;
        }
    };
    
    map <line, int> vis;
    
    void add(int x, int y, int z){
        e[++ecnt].to = y, e[ecnt].w = z, e[ecnt].nex = last[x], last[x] = ecnt;
    }
    
    void dfs(int x, int fa){
        for(int to, i=last[x];i;i=e[i].nex){
            to = e[i].to; if(to == fa) continue;
            dfs(to, x);
            if(ans < f[x]+f[to]+e[i].w) ans = f[x]+f[to]+e[i].w;
            if(f[x] < f[to]+e[i].w) f[x] = f[to]+e[i].w;
        }
    }
    
    int main(){
        ios::sync_with_stdio(false);
        int x, y, z; cin >> n;
        for(int i=1;i<=n-2;i++){
            cin >> x >> y >> z;
            if(x > y) swap(x, y); if(y > z) swap(y, z); if(x > y) swap(x, y);
            if(vis[(line){ x, y }]) add(i, vis[(line){ x, y }], 1), add(vis[(line){ x, y }], i, 1);
            else vis[(line){ x, y }] = i;
            if(vis[(line){ y, z }]) add(i, vis[(line){ y, z }], 1), add(vis[(line){ y, z }], i, 1);
            else vis[(line){ y, z }] = i;
            if(vis[(line){ x, z }]) add(i, vis[(line){ x, z }], 1), add(vis[(line){ x, z }], i, 1);
            else vis[(line){ x, z }] = i;
        }
        dfs(1, -1);
        cout << ans+1 << endl;
        return 0;
    }
    
  • 相关阅读:
    fatal error LNK1123: 转换到 COFF 期间失败:文件无效或损坏
    CI:模拟进化与遗传算法
    贝叶斯网络
    朴素贝叶斯模型
    概率与不确定性(乘法法则与贝叶斯法则)
    关于“启发式”搜索的一个形象解释
    Python 字符串与数字拼接报错
    无法启动此程序因为计算机中丢失 xxx.dll
    Python 以指定的概率选取元素
    验证码之SimpleCaptcha (二)
  • 原文地址:https://www.cnblogs.com/BCOI/p/9518959.html
Copyright © 2011-2022 走看看