zoukankan      html  css  js  c++  java
  • 「日常训练」Paths and Trees(Codeforces Round 301 Div.2 E)

    题意与分析

    题意是这样的,定义一个从某点出发的所有最短路方案中,选择边权和最小的最短路方案,称为最短生成树
    现在求一棵最短生成树,输出总边权和与选取边的编号。

    我们首先要明白这样一个结论:对一个图求Dijkstra后,把所有得到的最短路边全部连起来,生成的图一定是一棵树,是不会有环的。原因自己推一下就可以感受到。
    那么这样一来,这个树相当于我们在Dijkstra的时候就已经得到了。记录边是Dijkstra的基本操作,而我们只需要考虑一下当最短路相等时谁更优的情况并更新就可以了。

    代码

    #include <bits/stdc++.h>
    #define MP make_pair
    #define PB emplace_back
    #define fi first
    #define se second
    #define ZERO(x) memset((x), 0, sizeof(x))
    #define ALL(x) (x).begin(),(x).end()
    #define rep(i, a, b) for (repType i = (a); i <= (b); ++i)
    #define per(i, a, b) for (repType i = (a); i >= (b); --i)
    #define QUICKIO                  
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0);
    using namespace std;
    using ll=long long;
    using repType=int;
    
    struct Edge
    {
        int u, v;
        ll w;
        Edge() {}
        Edge(int _u, int _v, ll _w): u(_u), v(_v), w(_w) {}
        bool
        operator < (const Edge& rhs) const
    	{
            if(w==rhs.w)
    			{ return (u==rhs.u)?v<rhs.v:u<rhs.u; }
            else { return w<rhs.w; }
        }
    };
    
    const int MAXN=300005;
    vector<Edge> edges;
    vector<int> G[MAXN];
    
    void
    add_edge(int u, int v, ll w)
    {
        edges.PB(u, v, w);
        G[u].PB(int(edges.size())-1);
    }
    
    ll dist[MAXN];
    int pre[MAXN]; // pre: last edge
    
    void
    dijkstra(int start)
    {
        memset(pre, -1, sizeof(pre));
        memset(dist, 0x3f, sizeof(dist));
        using P=pair<ll, int>;
        priority_queue<P, vector<P>, greater<> > pq; // <dist, pnt>: 大根堆
        dist[start]=0;
        pq.push(MP(0, start));
        while(!pq.empty())
        {
            auto now=pq.top(); pq.pop();
            int u=now.se;
            if(dist[u]<now.fi) { continue; }
            rep(i, 0, int(G[u].size())-1)
            {
                int v=edges[G[u][i]].v;
                ll  w=edges[G[u][i]].w;
                if(dist[v]>dist[u]+w)
                {
                    dist[v]=dist[u]+w;
                    pre[v]=G[u][i];
                    pq.push(MP(dist[v], v));
                }
                else if(dist[v]==dist[u]+w && edges[pre[v]].w>edges[G[u][i]].w)
    				{ pre[v]=G[u][i]; }
            }
        }
    }
    
    int
    main()
    {
    	int n, m;
        scanf("%d%d", &n, &m);
        rep(i, 1, m)
        {
            int u, v;
            ll w;
            scanf("%d%d%lld", &u, &v, &w);
            add_edge(u, v, w);
            add_edge(v, u, w);
        }
    
        int stp; scanf("%d", &stp);
        dijkstra(stp);
    
        ll ans=0;
        rep(i, 1, n) if(i!=stp) { ans+=edges[pre[i]].w; }
        printf("%lld
    ", ans);
        rep(i, 1, n) if(i!=stp) { printf("%d ", pre[i]/2+1); }
        printf("
    ");
    
        return 0;
    }
    
    如非注明,原创内容遵循GFDLv1.3发布;其中的代码遵循GPLv3发布。
  • 相关阅读:
    jdk.exe转zip免安装
    jdk全版本下载链接
    Cesium primitive绘制折线和多边形
    sql调优的几种方式
    maven操作
    如何设计高并发系统?
    用友华表cell的程序发布
    OpenCV异常问题(一)
    js jquery window 高 宽
    sql中游标的使用一
  • 原文地址:https://www.cnblogs.com/samhx/p/cfr303d2e.html
Copyright © 2011-2022 走看看