zoukankan      html  css  js  c++  java
  • BZOJ2753 SCOI2012滑雪与时间胶囊(最小生成树)

      首先显然可以把所有能到的点拎出来建个新图,这样第一问也就做好了。

      剩下的部分似乎是一个裸的最小树形图。但显然这个东西是没什么学的必要的并且不太能跑过去。

      考虑建出来的图有什么性质。可以发现如果没有高度相等的点这就是个DAG。DAG的最小树形图只需要每个点选一条最短入边即可,最优性显然。或者说是将边从小到大排序后若合法则选入。

      然后考虑高度相等的点。如果某条边的两端点已经通过入边连在一起,两个点就相当于已连通,若加入该边则形成环;而如果通过出边连在一起,仍然是未连通的。

      那么按照终点高度为第一关键字,边权为第二关键字给边排序。这样即保证了不会通过出边将两点连通。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 1000010
    int n,m,h[N],p[N],p_new[N],t=0,fa[N];
    bool flag[N];
    long long ans=0;
    struct data{int to,nxt,len;
    }edge[N<<1];
    struct data2
    {
        int x,y,z;
        bool operator <(const data2&a) const
        {
            return h[y]>h[a.y]||h[y]==h[a.y]&&z<a.z;
        }
    }e[N<<1]; 
    void addedge(int x,int y,int z){t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].len=z,p[x]=t;}
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    void dfs(int k)
    {
        flag[k]=1;
        for (int i=p[k];i;i=edge[i].nxt)
        if (!flag[edge[i].to]) dfs(edge[i].to);
    }
    void rebuild()
    {
        t=0;
        for (int i=1;i<=n;i++)
        if (flag[i])
            for (int j=p[i];j;j=edge[j].nxt)
            if (flag[edge[j].to]) t++,e[t].x=i,e[t].y=edge[j].to,e[t].z=edge[j].len;
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2753.in","r",stdin);
        freopen("bzoj2753.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read();
        for (int i=1;i<=n;i++) h[i]=read();
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            if (h[x]>=h[y]) addedge(x,y,z);
            if (h[y]>=h[x]) addedge(y,x,z);
        }
        dfs(1);
        t=0;
        for (int i=1;i<=n;i++) if (flag[i]) t++;
        cout<<t<<' ';
        rebuild();
        sort(e+1,e+t+1);
        for (int i=1;i<=n;i++) fa[i]=i;
        for (int i=1;i<=t;i++)
        if (find(e[i].x)!=find(e[i].y)) ans+=e[i].z,fa[find(e[i].x)]=find(e[i].y);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    数据库索引学习
    JavaScript提高:002:ASP.NET使用easy UI实现tab效果
    jQuery效果之显示与隐藏
    leetcode
    走进Struts2(五)— 值栈和OGNL
    Html中的超链接
    再理解 as3.0接口
    easyui combobox 三级级联 input 两种实现
    三层登录实例VB.NET版具体解释---理论加实战篇
    如何用Delphi开发网游外挂
  • 原文地址:https://www.cnblogs.com/Gloid/p/9610010.html
Copyright © 2011-2022 走看看