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

    题目:http://61.187.179.132/JudgeOnline/problem.php?id=2753

    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。

     
    题解:
      题目的意思就是首先找到从编号为一的点开始走,能走的一定是高度不高于它的点,然后得到一个点集,把边加进去后得到一张新图,求这个图的最小树形图即可了。
     
      题意如此简单………………利用了该题的某些神奇性质………………把边按终点的高度为第一关键字,边长为第二关键字,排个序后就可以做了…………………………注意答案要64为整数即可…………………………
     
    View Code
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 
     7 using namespace std;
     8 
     9 const int maxn=100001;
    10 const int maxm=2000001;
    11 
    12 int sum,en,h[maxn],f[maxn],n,m;
    13 
    14 long long ans;
    15 
    16 bool use[maxn];
    17 
    18 queue<int> que;
    19 
    20 struct edge
    21 {
    22        int s,e,d;
    23        edge *next;
    24 }*v[maxn],ed[maxm];
    25 
    26 void add_edge(int s,int e,int d)
    27 {
    28      en++;
    29      ed[en].next=v[s];v[s]=ed+en;v[s]->s=s;v[s]->e=e;v[s]->d=d;
    30 }
    31 
    32 void bfs()
    33 {
    34      use[1]=true;
    35      sum=1;
    36      que.push(1);
    37      f[1]=1;
    38      while (que.size())
    39      {
    40            int now=que.front();
    41            que.pop();
    42            for (edge *e=v[now];e;e=e->next)
    43                if (!use[e->e])
    44                {
    45                               f[e->e]=e->e;
    46                               use[e->e]=true;
    47                               sum++;
    48                               que.push(e->e);
    49                }
    50      }
    51 }
    52 
    53 bool cmp(edge a,edge b)
    54 {
    55      return h[a.e]>h[b.e] || (h[a.e]==h[b.e] && a.d<b.d);
    56 }
    57 
    58 int getf(int now)
    59 {
    60     return (f[now]==now)?now:f[now]=getf(f[now]);
    61 }
    62 
    63 int main()
    64 {
    65     freopen("ski.in","r",stdin);
    66     freopen("ski.out","w",stdout);
    67     
    68     scanf("%d%d",&n,&m);
    69     for (int a=1;a<=n;a++)
    70         scanf("%d",&h[a]);
    71     for (int a=1;a<=m;a++)
    72     {
    73         int x,y,d;
    74         scanf("%d%d%d",&x,&y,&d);
    75         if (h[x]>=h[y]) add_edge(x,y,d);
    76         if (h[y]>=h[x]) add_edge(y,x,d);
    77     }
    78     bfs();
    79     sort(ed+1,ed+en+1,cmp);
    80     for (int a=1;a<=n;a++)
    81     f[a]=a;
    82     for (int a=1;a<=en;a++)
    83     {
    84         if (!use[ed[a].s] || !use[ed[a].e]) continue;
    85         int s=ed[a].s,e=ed[a].e;
    86         int fx=getf(s),fy=getf(e);
    87         if (fx!=fy)
    88         {
    89                    ans=ans+ed[a].d;
    90                    f[fx]=fy;
    91         }
    92     }
    93     printf("%d %lld\n",sum,ans);
    94     
    95     return 0;
    96 }
  • 相关阅读:
    P24—动态数组没有{}
    JavaB站学习————接口在开发中的作用
    JavaB站学习————extends和implements同时出现
    JavaB站学习————一个类可以实现多个接口以及接口的总结
    JavaB站学习————接口和多态联合使用。
    01日语五十音
    07 递归&&命名风格&&作业(结构体,malloc,函数,递归)
    JavaB站学习——作业16
    电子书
    破解压缩包
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2490889.html
Copyright © 2011-2022 走看看