双向spfa的模板 POJ1511

双向的spfa遍历的时候
(别忘了初始化 多组输入)
对于存放的边转化的问题 可以有多种实现方式
链式前向星的存储
我们可以开两个边集的数组来实现(一次就可以完成)
也可以通过一个 数组的储存来实现(两次循环的加边)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <cmath>

using namespace std;
#define inf 0x3f3f3f3f
typedef long long ll;
const int MAXN = 1e6+7;
int n,m,t,cnt,s = 1;
ll ans;
ll dis[MAXN];
int vis[MAXN];
int head[MAXN];
int a[MAXN][3];// 用这样一个数组 来存放 输入的边的信息 这样可以 通过重新加边 来实现 第二次的 spfa的遍历
struct node
{
    
    
    int to,next,w;
}edge[MAXN];

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

void init()
{
    
    
    memset(head,0,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(dis,inf,sizeof(dis));
    cnt = 0;
    dis[s] = 0;
}

void spfa()
{
    
    
    queue<int>q;
    q.push(s);
    vis[s] = 1;
    while(!q.empty())
    {
    
    
        int top = q.front();
        q.pop();
        vis[top] = 0;
        for(int i = head[top];i != 0;i = edge[i].next)
        {
    
    
            if(dis[edge[i].to] > dis[top] + edge[i].w)
            {
    
    
                dis[edge[i].to] = dis[top] + edge[i].w;
                if(!vis[edge[i].to])
                {
    
    
                    vis[edge[i].to] = 1;
                    q.push(edge[i].to);
                }
            }
        }
    }
    for(int i = 1;i <= n;i ++)
        ans += dis[i];
}

int main()
{
    
    
    cin>>t;
    while(t--)
    {
    
    
        scanf("%d%d",&n,&m);
        //int s,e,cost;
        ans = 0;
        init();
        for(int i = 1;i <= m;i ++)
        {
    
    
            scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
            addedge(a[i][0],a[i][1],a[i][2]);
        }
        spfa();
        init();
        for(int i = 1;i <= m;i ++)
            addedge(a[i][1],a[i][0],a[i][2]);
        spfa();
        printf("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45672411/article/details/104557332