poj1511解题报告(SPFA算法)

题目大意:给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1)

解题思路:使用spfa+邻接链表来做,因为要求来回的最短距离之和,所以先用spfa求一遍最短路,再把每条边反过来(a到b的边变成b到a的边)再用spfa求一遍最短路。

注意:结果要用long long 来储存

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxN=1000000+1000;
const int  INF=(1<<30);

int head[2][maxN],T,vis[maxN],n,m;
long long d[maxN];
struct Edge
{
    int e,next,w;
} edge[2][maxN];

void spfa(int cap){
    int v,i,b;
    queue <int>q;
    for(i=1;i<=n;i++){
        d[i]=INF;
        vis[i]=0;
    }
    q.push(1);
    vis[1]=1;
    d[1]=0;//1为起始点
    while(!q.empty()){
        v=q.front();
        q.pop();
        vis[v]=0;
        for(i=head[cap][v];i!=-1;i=edge[cap][i].next){
            b=edge[cap][i].e;
            if(d[b]>d[v]+edge[cap][i].w){
                d[b]=d[v]+edge[cap][i].w;
                if(!vis[b]){
                    vis[b]=1;
                    q.push(b);
                }
            }
        }
    }
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);

        for(int i=1; i<=n; i++)
        {
                head[0][i]=-1;
                head[1][i]=-1;
        }
             for(int i=0;i<m;i++)//½¨Á¢ÁÙ½ÓÁ´±í
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                edge[0][i].w=c;
                edge[0][i].e=b;
                edge[0][i].next=head[0][a];
                head[0][a]=i;
                edge[1][i].w=c;
                edge[1][i].e=a;
                edge[1][i].next=head[1][b];
                head[1][b]=i;
            }
            long long ans=0;
              spfa(0);
                for(int i=1;i<=n;i++) ans+=d[i];
                spfa(1);
                for(int i=1;i<=n;i++) ans+=d[i];
                printf("%lld\n",ans);
        }
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值