POJ 1511 SPFA+邻接表 Invitation Cards

 题目大意:

计算从 1 点 到 其他所有点的 往返距离之和, 因为是 有向图, 所以我们需要将图反存 一次, 然后求两次单源最短路, 结果就出来了。

 

#include <iostream>

#include <cstdlib>

#include <cstdio>

#include <algorithm>

#include <vector>

#include <queue>

using namespace std;

#define INF 0xffffffff

#define maxn 1000005



struct Edge

{

    int w, e;

};



int UseCount[maxn], m ,n;

bool Use[maxn];

long long dist[2][maxn];



vector<vector<Edge> > G[2];



void Init()

{

    G[0].clear();

    G[1].clear();

    G[0].resize(n+1);

    G[1].resize(n+1);

    for(int i=1; i<=n; i++)

    {

        dist[1][i] = dist[0][i] = INF, Use[i] = false;

    }

}

long long Spfa(int k)

{

    Edge P, Pn;

    P.w = 0, P.e = 1;

    dist[k][1] = 0;

    queue<Edge>Q;

    Q.push(P);



    while( !Q.empty() )

    {

        P = Q.front();

        Q.pop();

        Use[P.e] = false;

        int len = G[k][P.e].size();



        for(int i=0; i<len; i++)

        {

            Pn = G[k][P.e][i];



            if(dist[k][Pn.e] > dist[k][P.e] + Pn.w)

            {

                dist[k][Pn.e] = dist[k][P.e] + Pn.w;

                if( !Use[Pn.e] )

                {

                    Q.push(Pn);

                    Use[Pn.e] = true;

                }

            }

        }

    }



    long long sum = 0;



    for(int i=1; i<=n; i++)

        sum += dist[k][i];

    return sum;

}



int main()

{

    int T;

    Edge P;

    scanf("%d",&T);

    while(T--)

    {



        scanf("%d%d",&n,&m);

        Init();

        for(int i=0; i<m; i++)

        {

            int a, b, c;

            scanf("%d%d%d",&a,&b,&c);

            P.e = b, P.w = c;

            G[0][a].push_back(P);

            P.e = a;

            G[1][b].push_back(P);

        }

        

        long long sum = 0;

        

        sum += Spfa(0);

        sum += Spfa(1);



        printf("%I64d\n",sum);

    }

    return 0;

}

 

 

你可能感兴趣的:(SPFA)