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

    bfs+最小树形图+kruskal算法。

    最小树形图形象地来说就是有向图的最小生成树,这个不能拿kruskal算法或者是prim算法直接求,否则会错。

    就是w[u][v]!=w[v][u]的情况。

    而这道题用朱刘算法肯定是行不通的。

    但是这道题的有向边并不是边的性质,而是点的高度决定的。这样我们就可以分层求最小生成树。

    如果加进高度为h的点,只需用kruskal算法选最短的边就可以了,而且不会影响到后面的选择。

    于是我们把kruskal算法的排序改成以结尾点高度为第一关键字降序和边长度为第二关键字升序排序。。。(意会,要不看cmp,嗯。)

    这样就可以辣。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 100000 + 10;
    const int maxm = 2000000 + 10;
    
    int read(){
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    struct Edge {
        int u,v,d;    
    }e[maxm];
    
    int h[maxn],f[maxn];
    int g[maxn],v[maxm],next[maxm],eid;
    int res1,n,m;
    long long res2;
    bool vis[maxn];
    int q[maxm],l,r,u;
    
    void addedge(int a,int b) {
        v[eid]=b; next[eid]=g[a]; g[a]=eid++;
    }
    
    bool cmp(Edge a,Edge b) {
        if(h[a.v]!=h[b.v]) return h[a.v]>h[b.v];
        return a.d<b.d;     
    }
    
    int find(int x) {
        return f[x]==x?x:f[x]=find(f[x]);
    }    
    
    int main() {
        memset(g,-1,sizeof(g));
        n=read(); m=read();
        for(int i=1;i<=n;i++) h[i]=read();
        for(int i=1,u,v;i<=m;i++) {        
            u=read(); v=read(); e[i].d=read();
            if(h[u]>=h[v]) addedge(u,v);
            if(h[v]>=h[u]) {addedge(v,u); swap(u,v);}
            e[i].u=u; e[i].v=v;
        }
        sort(e+1,e+m+1,cmp);
        
        vis[q[r++]=1]=1,res1=1;
        while(l<r) {
            u=q[l++];
            for(int i=g[u];~i;i=next[i]) if(!vis[v[i]]) {
                vis[q[r++]=v[i]]=1;
                res1++;
            }
        }
        
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=1,ru,rv;i<=m;i++) if(vis[e[i].u]&&vis[e[i].v]) {
            ru=find(e[i].u);
            rv=find(e[i].v);
            if(ru!=rv) {
                res2+=e[i].d;
                f[rv]=ru;
            }
        }
        printf("%d %lld
    ",res1,res2);
        return 0;
    }

  • 相关阅读:
    as3 绕中心点旋转
    TweenMax
    As3支持的Html标签一览
    AS3.0 静音和停止所有声音
    as3 如何判断同时按下两个键
    前置窗体
    系统音效控制
    LocalConnection
    as3代码实现调用摄像头
    air 加载网页
  • 原文地址:https://www.cnblogs.com/invoid/p/5635995.html
Copyright © 2011-2022 走看看