邻接表实现,单源最短路径

    本篇文章,参考了y990041769同学的blog,他的博客地址如下[http://blog.csdn.net/y990041769/article/details/18367665]
    受他启发,这道题实际上从1出发到某个点,以及从此点回到1的最短距离。其实感觉只要建图,跑一遍spfa之后,再逆序跑一遍spfa就好了,可是在建图的时候坑死一大片,建图的时候用vector是会t的,虽然本题给了8s(Orz!)
    参考邻接表的模板,写了一个能过的版本,现在分享出来。
    先上模板:
///模板一,建图和保存节点信息

int H[N];  //存头节点 
struct   //记录节点信息 
{  
    int v;  ///相当于节点的终点
    int count;  ///相当于边权
    int next;  ///记录当前节点和下一个节点的关系
}E[N];  

int T,n,m,top;  

void Readmap(int m)  //读图 
{  
    memset(H,-1,sizeof(H));  
    int top=0;  
    for(int i=0;i<m;i++){  
        scanf("%d%d%d",&x[i],&y[i],&c[i]);  
        E[top].v=y[i];E[top].count=c[i];  
        E[top].next=H[x[i]];  
        H[x[i]]=top++;  
    }  
}  
///邻接表spfa模板

long long SPFA(int st)
{
    for(int i=1;i<=n;i++)
        sp[i]=inf;
    sp[1]=0;
    queue<int> q;
    q.push(st);
    while(!q.empty())
    {
        int kai=q.front();q.pop();
        for(int i=H[kai];i!=-1;i=E[i].next)
        {
            if(sp[E[i].v]>E[i].count+sp[kai]){
                sp[E[i].v]=E[i].count+sp[kai];
                q.push(E[i].v);
            }
        }
    }    ///spfa已经讲过,这里不再赘述
    long long ans=0;
    for(int i=1;i<=n;i++)
        ans+=sp[i];
    return ans;
}

///@zhangxiaoyu
///2015/8/10

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<stack>
#include<queue>
#include<cmath>
#include<iostream>
using namespace std;
#define maxn 1000005
#define INF 0x3f3f3f3f
typedef long long LL;

int x[maxn],y[maxn],c[maxn],sp[maxn];
int head[maxn];   ///保存头结点,即哪些边是与当前节点连接

struct node{ ///记录节点信息
   int v;    ///相当于终点
   int cnt;  ///相当于len
   int next;  ///记录此节点和下一个节点的关系
};

struct node E[maxn];
int n,m;

void input1()
{
    int top=0;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x[i],&y[i],&c[i]);
        E[top].v=y[i];
        E[top].cnt=c[i];       ///权值
        E[top].next=head[x[i]];///记录当前节点前驱
        head[x[i]]=top++;
    }
}

void input2()
{
    int top=0;
    for(int i=1;i<=m;i++)
    {
        E[top].v=x[i];
        E[top].cnt=c[i];
        E[top].next=head[y[i]];
        head[y[i]]=top++;
    }
}

LL spfa(int st)
{
    int j;
    for(int i=1;i<=n;i++)
        sp[i]=INF;
    sp[1]=0;
    queue<int>qq;
    qq.push(st);
    while(!qq.empty())
    {
        j=qq.front();
        qq.pop();
        for(int i=head[j];i!=-1;i=E[i].next)
        {
            if(sp[E[i].v]>E[i].cnt+sp[j])
            {
                sp[E[i].v]=E[i].cnt+sp[j];
                qq.push(E[i].v);
            }
        }
    }
    LL ans=0;
    for(int i=1;i<=n;i++)
        ans+=sp[i];
    return ans;
}

int main()
{
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        LL ans=0;
        int u=1;
        scanf("%d%d",&n,&m);
        memset(E,INF,sizeof(INF));
        memset(head,-1,sizeof(head));
        input1();
        ans+=spfa(u);
        memset(E,INF,sizeof(E));
        memset(head,-1,sizeof(head));
        input2();
        ans+=spfa(u);
        printf("%lld\n",ans);
    }
    return 0;
}
全部评论

相关推荐

不知道怎么取名字_:看来现在卷的,这种单位都开始提高要求了
点赞 评论 收藏
分享
04-19 18:50
已编辑
长沙学院 Java
个人背景:学院二本计科专业&nbsp;大二开始实习个人经历:安克创新&nbsp;、理想汽车、字节跳动碎碎念:我做事只有三分钟热度。看到进了大厂的同学,我会羡慕,也会跟着努力上进;但遇到好看的小说,我又会放下手头的事沉迷其中,之前的坚持也就中断了。我有些自卑,总觉得自己学历和外貌都不够好。之前偶然在网上受到关注,我就喜欢上了上网,因为这里有很多人认可我。但我也很在意别人的评价,偶尔看到嘲讽的言论,会触发我的自卑情绪,让我感到愤怒。有时候我会强硬地回怼,有时候又会懦弱地选择无视。我也有虚荣心。不管是拿到安克、理想还是字节的机会,我在分享的时候都会带着这份心思。我会特意强调自己学历不好,是为了衬托出过程的艰难,以此显得自己更厉害。我知道,人往往会炫耀自己缺少的东西,来掩盖内心的空洞。我总想着走捷径,不太喜欢踏踏实实地做事。找实习的时候,我花了更多时间在研究面试技巧上,而不是提升专业能力。我会反复听面试录音分析技巧,看面试教程学习怎么和不同的面试官沟通,还会每天自言自语练习语言表达,同学都觉得我有点奇怪。我的实习生涯里,侥幸和运气占了很大一部分。我总在想,如果有一天我失去了这份幸运,这些特质可能会让我一蹶不振。ps:&nbsp;很多人会问我学习路线和经验&nbsp;但是就像我上面说的&nbsp;我的实习过程靠的很多是关键节点的运气&nbsp;技术上面我可能不如很多人&nbsp;&nbsp;所以请大家理性求助和理性参考我的回答&nbsp;附上我的投递记录
我的offer在哪里...:从去年看到现在,飞升哥就是榜样
我的求职进度条
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务