zoukankan      html  css  js  c++  java
  • Codeforces Round #303 (Div. 2)(CF545) E Paths and Trees(最短路+贪心)

    题意

    求一个生成树,使得任意点到源点的最短路等于原图中的最短路。再让这个生成树边权和最小。

    http://codeforces.com/contest/545/problem/E

    思路

    先Dijkstra一下,再对每个点连的边判断是不是最短路上的边,如果是那再贪心取最小的边即可。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll inf=1e18;
    const int N=6e5+5;
    struct qnode
    {
        ll v;
        ll c;
        qnode(ll _v=0,ll _c=0):v(_v),c(_c){}
        bool operator <(const qnode &r)const
        {
            return c>r.c;
        }
    };
    struct edge
    {
        ll v,cost;
        int next;
    };
    edge eg[N];
    int head[N];
    ll dist[N],tot=1;
    bool vis[N];
    void Dijkstra(int n,int sta)
    {
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;i++)   dist[i]=inf;
        priority_queue<qnode> pq;
        dist[sta]=0;
        pq.push(qnode(sta,0));
        qnode tmp;
        while(!pq.empty())
        {
            tmp=pq.top();
            pq.pop();
            int u=tmp.v;
            if(vis[u])continue;
            vis[u]=true;
            for(int i=head[u];~i;i=eg[i].next)
            {
                int v=eg[i].v;
                int cost=eg[i].cost;
                if(!vis[v]&&dist[v]>dist[u]+cost)
                {
                    dist[v]=dist[u]+cost;
                    pq.push(qnode(v,dist[v]));
                }
            }
        }
    }
    void init()
    {
        memset(head,-1,sizeof(head));
        tot=1;
    }
    void addedge(int u,int v,ll w)
    {
        eg[tot].v=v;
        eg[tot].cost=w;
        eg[tot].next=head[u];
        head[u]=tot++;
    }
    int main()
    {
        int n,m;
        init();
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            int u,v;
            ll w;
            scanf("%d%d%lld",&u,&v,&w);
            addedge(u,v,w);
            addedge(v,u,w);
        }
        int rt;
        scanf("%d",&rt);
        Dijkstra(n,rt);
        vector<int> ans;
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            if(i!=rt)
            {
                ll mn=inf,mi;
                for(int j=head[i];~j;j=eg[j].next)
                {
                    int v=eg[j].v;
                    if(dist[i]==dist[v]+eg[j].cost)
                    {
                        if(mn>eg[j].cost)
                        {
                            mn=eg[j].cost;
                            mi=(j+1)/2;
                        }
                    }
                }
                ans.push_back(mi);
                sum+=mn;
            }
        }
        printf("%lld
    ",sum);
        for(int i : ans)
        {
            printf("%d ",i);
        }
        puts("");
        return 0;
    }
    
  • 相关阅读:
    可变长参数
    函数的参数
    函数
    文件操作
    字符编码
    数据类型的内置方法:集合
    数据类型的内置方法:元组
    数据类型的内置方法:字典
    数据类型内置方法:列表
    js对对象引用
  • 原文地址:https://www.cnblogs.com/mcq1999/p/11582023.html
Copyright © 2011-2022 走看看