zoukankan      html  css  js  c++  java
  • [SCOI 2012]滑雪与时间胶囊

    Description

    a180285非常喜欢滑雪。他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi。a180285能从景点i 滑到景点j 当且仅当存在一条i 和j 之间的边,且i 的高度不小于j。 与其他滑雪爱好者不同,a180285喜欢用最短的滑行路径去访问尽量多的景点。如果仅仅访问一条路径上的景点,他会觉得数量太少。于是a180285拿出了他随身携带的时间胶囊。这是一种很神奇的药物,吃下之后可以立即回到上个经过的景点(不用移动也不被认为是a180285 滑行的距离)。请注意,这种神奇的药物是可以连续食用的,即能够回到较长时间之前到过的景点(比如上上个经过的景点和上上上个经过的景点)。 现在,a180285站在1号景点望着山下的目标,心潮澎湃。他十分想知道在不考虑时间
    胶囊消耗的情况下,以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前提下使得滑行总距离最小)。你能帮他求出最短距离和景点数吗?

    Input

    输入的第一行是两个整数N,M。
    接下来1行有N个整数Hi,分别表示每个景点的高度。
    接下来M行,表示各个景点之间轨道分布的情况。每行3个整数,Ui,Vi,Ki。表示
    编号为Ui的景点和编号为Vi的景点之间有一条长度为Ki的轨道。

    Output

    输出一行,表示a180285最多能到达多少个景点,以及此时最短的滑行距离总和。 

    Sample Input

    3 3
    3 2 1
    1 2 1
    2 3 1
    1 3 10

    Sample Output

    3 2

    HINT

    【数据范围】

        对于30%的数据,保证 1<=N<=2000

        对于100%的数据,保证 1<=N<=100000

    对于所有的数据,保证 1<=M<=1000000,1<=Hi<=1000000000,1<=Ki<=1000000000。

    题解

    对于第一问,我们直接遍历一遍就好了。

    对于第二问,把第一问中的边取出。结点具有层次性,且不具有环。把边先按终点高度排序为第一关键字(从大到小),边长为第二关键字排序(从大到小)之后,就会保证优先到高点,同高点之间选最小边。

     1 //It is made by Awson on 2017.10.26
     2 #include <set>
     3 #include <map>
     4 #include <cmath>
     5 #include <ctime>
     6 #include <cmath>
     7 #include <stack>
     8 #include <queue>
     9 #include <vector>
    10 #include <string>
    11 #include <cstdio>
    12 #include <cstdlib>
    13 #include <cstring>
    14 #include <iostream>
    15 #include <algorithm>
    16 #define LL long long
    17 #define link LINK
    18 #define Min(a, b) ((a) < (b) ? (a) : (b))
    19 #define Max(a, b) ((a) > (b) ? (a) : (b))
    20 #define Abs(a) ((a) < 0 ? (-(a)) : (a))
    21 using namespace std;
    22 const int N = 1e5;
    23 const int M = 1e6;
    24 
    25 int n, m, h[N+5], u, v, w, ans1;
    26 LL ans2;
    27 struct tt {
    28   int to, cost, next;
    29 }edge[(M<<1)+5];
    30 struct ss {
    31   int from, to, cost;
    32   bool operator < (const ss &b) const{
    33     return h[to] == h[b.to] ? cost < b.cost : h[to] > h[b.to];
    34   }
    35 }link[(M<<1)+5];
    36 int path[N+5], top;
    37 bool vis[N+5];
    38 int st[N+5];
    39 
    40 int find(int r) {
    41   return st[r] ? st[r] = find(st[r]) : r;
    42 }
    43 void bfs() {
    44   queue<int>Q;
    45   while (!Q.empty()) Q.pop();
    46   Q.push(1); vis[1] = 1;
    47   while (!Q.empty()) {
    48     int u = Q.front(); ans1++; Q.pop();
    49     for (int i = path[u]; i; i = edge[i].next)
    50       if (!vis[edge[i].to]) {
    51     Q.push(edge[i].to); vis[edge[i].to] = 1;
    52       }
    53   }
    54 }
    55 void add(int u, int v, int c) {
    56   edge[++top].to = v;
    57   edge[top].cost = c;
    58   edge[top].next = path[u];
    59   path[u] = top;
    60 }
    61 void Kruskal() {
    62   int cnt = 0;
    63   for (int u = 1; u <= n; u++)
    64     for (int j = path[u]; j; j = edge[j].next)
    65       if (vis[u] && vis[edge[j].to])
    66     link[++cnt].from = u, link[cnt].to = edge[j].to, link[cnt].cost = edge[j].cost;
    67   sort(link+1, link+1+cnt);
    68   for (int i = 1; i <= cnt; i++) {
    69     int u = link[i].from, v = link[i].to, c = link[i].cost;
    70     int p = find(u), q = find(v);
    71     if (p != q) {
    72       st[p] = q; ans2 += c;
    73     }
    74   }
    75 }
    76 void work() {
    77   scanf("%d%d", &n, &m);
    78   for (int i = 1; i <= n; i++) scanf("%d", &h[i]);
    79   for (int i = 1; i <= m; i++) {
    80     scanf("%d%d%d", &u, &v, &w);
    81     if (h[u] >= h[v]) add(u, v, w);
    82     if (h[v] >= h[u]) add(v, u, w);
    83   }
    84   bfs();
    85   Kruskal();
    86   printf("%d %lld
    ", ans1, ans2);
    87 }
    88 int main() {
    89   work();
    90   return 0;
    91 }
  • 相关阅读:
    解析url
    初学react
    移动端判断用户滑动方向
    冒泡排序、快速排序、数组去重
    Angular Material主题配置
    reset()方法的使用、jq下面reset()的正确使用方法
    conts、var 、let的区别
    NLP
    mybatis的执行流程
    PHP递归算法示例:打印无限级数组元素的值
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7739434.html
Copyright © 2011-2022 走看看