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\n",sum);
    for(int i : ans)
    {
        printf("%d ",i);
    }
    puts("");
    return 0;
}
posted @ 2019-09-25 00:12  MCQ1999  阅读(169)  评论(0编辑  收藏  举报