I - Paths and Trees(迪杰斯特拉)

点击打开链接

大晚上的打代码确实挺心累的,本来想这题搞完就睡,没想到搞了好久

题目将从某点出发的所有最短路方案中,选择边权和最小的最短路方案,称为最短生成树。

题目要求一颗最短生成树,输出总边权和与选取边的编号。

1.测试数据比较强 最大值要放很大 const ll inf=0x7fffffffffffff;(13个)

2.  typedef pair<long long, int> P;

 用到优先队列 priority_queue<P,vector<P>,greater<P> > q;

由于pair类型的使用比较繁琐,因为如果要定义多个形同的pair类型的时候,可以时候typedef简化声明:

本来是可以重载小于号 ,但重载后就超时了,还是去掉用默认的,即P在q中默认按P.first来比

/*struct cmp{
    bool operator() ( P a, P b ){


        return a.first< b.first; }
};*/

3.memset是按字节来填的,不能用来赋最大值,可以用fill 替代 fill(d,d+n+1,inf);格式和sort有点类似

4.主要算法把 迪杰斯特拉改了一下c【】用来存与该点绑定的边的cost,s用来存绑定的边

值得一提的是去掉了flag数组,目的是在最短路不变的情况下更新是否有更小权值的边


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<functional>
#define N 300005
#define ll long long
using namespace std;

const ll inf=0x7fffffffffffff;
struct edge
{
    int to,cost,id;
    edge(int t,int c,int d): to(t),cost(c),id(d){}
};
typedef pair<long long, int> P;
/*struct cmp{
    bool operator() ( P a, P b ){

        return a.first< b.first; }
};*/
vector<edge>G[N];
ll d[N],c[N];//c代表与该点绑定的边的cost
int m,n,s[N];//存与该节点绑定的边
void dij(int u)
{
    fill(d,d+n+1,inf);
    fill(c,c+n+1,inf);
    d[u]=0;
    priority_queue<P,vector<P>,greater<P> > q;
    q.push(P(d[u],u));
    while(!q.empty())
    {
        P p=q.top();
        q.pop();
        int v=p.second;
        //if(d[v] < p.first) continue;
        for(int i=0;i<G[v].size();i++)
        {
            edge e=G[v][i];
            if(d[e.to] >d[v] + e.cost )
            {
                d[e.to]= d[v] + e.cost;
                s[e.to]= e.id;
                c[e.to]= e.cost;
                q.push(P(d[e.to],e.to));
            }
            else if(d[e.to] ==d[v] + e.cost && c[e.to]>e.cost)
            {
                s[e.to]= e.id;
                c[e.to]= e.cost;
            }
        }
    }
}
int main(){
     int u,v,co;
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++){
         scanf("%d%d%d",&u,&v,&co);
         G[u].push_back(edge(v,co,i));
         G[v].push_back(edge(u,co,i));
     }
     scanf("%d",&u);
     dij(u);
     ll sum=0;
     for(int i=1;i<=n;i++){
         if(i!=u) sum+=c[i];
     }
     cout<<sum<<endl;
     for(int i=1;i<=n;i++){
         if(i!=u) cout<<s[i]<<' ';
     }
    return 0;
 }





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值