• 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

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

  • 相关阅读:
    The Python Standard Library
    Python 中的round函数
    Python文件类型
    Python中import的用法
    Python Symbols 各种符号
    python 一行写多个语句
    免费SSL证书(https网站)申请,便宜SSL https证书申请
    元宇宙游戏Axie龙头axs分析
    OLE DB provider "SQLNCLI10" for linked server "x.x.x.x" returned message "No transaction is active.".
    The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "xxx.xxx.xxx.xxx" was unable to begin a distributed transaction.
  • 原文地址:https://www.cnblogs.com/Silymtics/p/13721219.html
Copyright © 2020-2023  润新知