zoukankan      html  css  js  c++  java
  • P2573 [SCOI2012]滑雪 题解

    下午花了三个小时肝这道题,心态差点爆炸!

    下面是分析:

     1 题目要求:
     2 求最小生成树
     3 但是
     4 - a是从1号点开始的 --> 如果以后的某个点比一号高,则不可能到达 
     5 - a只能从高往低处滑
     6 - 可能某两个景点没有轨道连接 -->没有处在一个联通快里?
     7 
     8 生成树的要求:
     9 - 树根高度最大
    10 - 子节点的高度必须比父亲结点小 
    11 - 边权和尽可能小
    12 
    13 自己造的样例:
    14 输入:
    15 4 4
    16 4 2 3 1
    17 1 2 3
    18 2 3 2
    19 2 4 4 
    20 3 4 1
    21 
    22 输出:
    23 3 7

    从题解上爬的Solotion:

     1 为保证我们只会由高到低,我们就只建立由高向低的单向边即可。
     2 
     3 对于建立出来的图A,由1点开始宽搜,将扩展到的点和边加入一个新图B,
     4 所有扩展到的点便是能到达的最多点。
     5 
     6 我们再在这个新图上跑Kruskal求最小生成树,求得最短距离。
     7 
     8 对于排序部分,为保证有尽可能多的点在最小生成树里,
     9 我们按终点的高度为第一关键字从大到小排序,边长为第二关键字从小到大排序;
    10 
    11 这样就能保证拓展的点最多,进而再用最小生成树求最短距离。

    最终AC代码:

     1 /*
     2 Work By:Suzt_ilymtics
     3 */
     4 #include<iostream>
     5 #include<cstdio>
     6 #include<algorithm>
     7 #include<queue>
     8 using namespace std;
     9 const int MAXN=1e5+5;
    10 const int MAXM=1e6+6;
    11 struct edge{
    12     int from,to,nxt;
    13     long long w;
    14 }e_a[MAXM << 1],e_b[MAXM << 1];
    15 int head_a[MAXN],num_edge_a;
    16 int num_edge_b;
    17 int n,m,cnt;
    18 long long ans;
    19 int h[MAXN],f[MAXN];
    20 bool vis[MAXN];
    21 queue<int> q;
    22 
    23 int find(int x) {return f[x] == x ? x : f[x]=find(f[x]);}
    24 
    25 bool cmp(edge x,edge y){return h[x.to] == h[y.to] ? x.w < y.w : h[x.to] > h[y.to];}
    26 
    27 void add_a(int from,int to,int w){
    28     e_a[++num_edge_a].from = from;
    29     e_a[num_edge_a].to = to;
    30     e_a[num_edge_a].w = w;
    31     e_a[num_edge_a].nxt = head_a[from];
    32     head_a[from] = num_edge_a;
    33 }
    34 
    35 void add_b(int from,int to,int w){
    36     e_b[++num_edge_b].from = from;
    37     e_b[num_edge_b].to = to;
    38     e_b[num_edge_b].w = w;
    39 }
    40 
    41 void bfs(int x){
    42     q.push(x);vis[1]=1;
    43     while(!q.empty()){
    44         int t=q.front(); q.pop();
    45         for(int i=head_a[t];i;i=e_a[i].nxt){
    46             add_b(e_a[i].from,e_a[i].to,e_a[i].w);
    47             if(!vis[e_a[i].to]){
    48                 vis[e_a[i].to]=1;
    49                 q.push(e_a[i].to);
    50                 cnt++;
    51             }
    52         }
    53     }
    54 }
    55 
    56 void kls(){
    57     for(int i=1;i<=num_edge_b;++i){
    58         int uf=find(e_b[i].from),vf=find(e_b[i].to);
    59         if( uf == vf ) continue;
    60         else{
    61             f[uf] = vf;
    62             ans+=e_b[i].w;      
    63         }
    64     }
    65 }
    66 
    67 int main()
    68 {
    69     scanf("%d%d",&n,&m);
    70     for(int i=1;i<=n;++i){
    71         scanf("%d",&h[i]),f[i]=i;
    72     }
    73     for(int i=1,u,v,w;i<=m;++i){
    74         scanf("%d%d%d",&u,&v,&w);
    75         if(h[u]>=h[v]) add_a(u,v,w);
    76         if(h[u]<=h[v]) add_a(v,u,w);
    77     }
    78     bfs(1);
    79     sort(e_b+1,e_b+num_edge_b+1,cmp);
    80     kls();
    81     printf("%d %lld",cnt+1,ans);
    82     return 0;
    83 }

     The end

    (这篇文章终于能看了点)

  • 相关阅读:
    String与StringBuffer常用API
    Java常用类库与工具课后习题3-5
    Java异常课后习题编程题
    Java异常课后习题简答题
    Visio的快速使用和功能理念
    Google免费新书-《构建安全&可靠的系统》
    名字的由来
    日志分析-利用grep,awk等文本处理工具完成(2019-4-9)
    关于docker--详解安装,常规操作,导入导出等(2017-3-29)
    Thinkphp5-0-X远程代码执行漏洞分析(2019-1-11)
  • 原文地址:https://www.cnblogs.com/Silymtics/p/13721219.html
Copyright © 2011-2022 走看看