您的位置:首页 > 其它

codeforces 545 Round #303 (Div. 2) E Paths and Trees

2015-06-21 16:27 609 查看
求某个顶点的最短路径生成树,且边的总权值最小。如果有多个,输出任意一个即可。(输出最小权值以及所选的边)

选边的时候注意一下:如果u到v,与u到k到v的路径长度相同。应当选取后者。即尽可能经过多的顶点,这样可以保证总权值最小。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define N 300005
#define inf 0x3f3f3f3f3f3f3f3f
struct Edge{
    int to,next,id;
    LL w;
}edge[N<<1];

int cnt,n,head
,pre
;
LL low
,w
;
bool vis
;

inline void add(int u,int v,LL w,int id){
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    edge[cnt].id=id;
    head[u]=cnt++;
}

void spfa(int s)
{
    int i,j;
    memset(vis,0,sizeof(vis));
    vis[s]=1,low[s]=0;
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        int u=q.front();q.pop();
        vis[u]=0;
        for(i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(low[v]>low[u]+edge[i].w){
                low[v]=low[u]+edge[i].w;
                pre[v]=edge[i].id;
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
            else if(low[v]==low[u]+edge[i].w){
                if(w[pre[v]]>edge[i].w){
                    pre[v]=edge[i].id;
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
    }
}

int main()
{
    int m,i,u;
    scanf("%d%d",&n,&m);
    memset(low,inf,sizeof(low));
    memset(head,-1,sizeof(head));
    for(i=1;i<=m;++i){
        int x,y;
        LL z;
        scanf("%d%d%lld",&x,&y,&z);
        add(x,y,z,i);
        add(y,x,z,i);
        w[i]=z;
    }
    scanf("%d",&u);
    spfa(u);
    LL s=0;
    for(i=1;i<=n;++i) if(pre[i]) s+=w[pre[i]];
    printf("%lld\n",s);
    for(i=1;i<=n;++i) if(pre[i]) printf("%d ",pre[i]);
    puts("");
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: