zoukankan      html  css  js  c++  java
  • BZOJ2753: [SCOI2012]滑雪与时间胶囊

    【传送门:BZOJ2753


    简要题意:

      有n个景点,有m条边,每条边有长度,每个景点有一定的高度,i能走向j当且仅当i与j之间有边,而且i的高度大于等于j的高度,求从1出发,在遍历最多景点数的情况下,求出景点数和最短路径长度


    题解:

      开始还以为直接宽搜过的水题

      结果。。

      咳咳,讲题解讲题解

      首先用v[i]能否从1点走到i点,然后对于一条边x,y,只要有一个点的v为false时,这条边就是废的

      然后用最小生成树来做

      那么怎么处理每条边的优先级呢?

      首先我们按y的高度为第一优先级从大到小排,然后以长度为第二优先级从小到大排

      为什么?

      因为如果x能连向y,那么就说明h[x]>=h[y],所以,这样子做就能够保证走的一直是一条路径

      然后我们还要加一条0到1的边,长度为0,且把h[0]弄成无限大

      这样子就能够保证从1点开始走了

      看这数据范围也是要加long long的


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    int h[1100000];
    struct node
    {
        int x,y,next;
        LL d;
    }a[4100000];int last[1100000],len;
    void ins(int x,int y,LL d)
    {
        len++;
        a[len].x=x;a[len].y=y;a[len].d=d;
        a[len].next=last[x];last[x]=len;
    }
    bool v[1100000];
    void dfs(int x)
    {
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(v[y]==false)
            {
                v[y]=true;
                dfs(y);
            }
        }
    }
    int fa[1100000];
    bool cmp(node n1,node n2)
    {
        if(h[n1.y]>h[n2.y]) return true;
        if(h[n1.y]<h[n2.y]) return false;
        if(n1.d<n2.d) return true;
        if(n1.d>n2.d) return false;
    }
    int findfa(int x)
    {
        if(fa[x]!=x) fa[x]=findfa(fa[x]);
        return fa[x];
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&h[i]);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++)
        {
            int x,y;LL d;
            scanf("%d%d%lld",&x,&y,&d);
            if(h[x]>=h[y]) ins(x,y,d);
            if(h[x]<=h[y]) ins(y,x,d);
        }
        memset(v,false,sizeof(v));
        v[0]=v[1]=true;
        dfs(1);
        h[0]=999999999;
        ins(0,1,0);
        for(int i=0;i<=n;i++) fa[i]=i;
        sort(a+1,a+len+1,cmp);
        LL ans=0;int t=0;
        for(int i=1;i<=len;i++)
        {
            int x=a[i].x,y=a[i].y;
            if(v[x]==false||v[y]==false) continue;
            int fx=findfa(x),fy=findfa(y);
            if(fx!=fy)
            {
                fa[fy]=fx;
                ans+=a[i].d;
                t++;
            }
        }
        printf("%d %lld
    ",t,ans);
        return 0;
    }

     

  • 相关阅读:
    Linux tcpdump 命令详解与示例
    Linux 查看磁盘IO并找出占用IO读写很高的进程
    Rsync 服务部署与参数详解
    Linux curl 表单登录或提交与cookie使用
    Linux curl 常用示例
    Linux curl 命令详解
    Linux下使用 github+hexo 搭建个人博客07-next主题接入搜索和站点管理
    Linux下使用 github+hexo 搭建个人博客06-next主题接入数据统计
    Linux下使用 github+hexo 搭建个人博客05-next主题接入评论系统
    Linux下使用 github+hexo 搭建个人博客04-next主题优化
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8540252.html
Copyright © 2011-2022 走看看