poj 1511 Invitation Cards (spfa)

/*
      题目要求是给你一个有向图,求出顶点1到其他顶点的最短距离
      再加上其他的顶点到1的最短距离,结果是把这个和给输出。

      先对原图求一遍spfa。求得顶点1到其他顶点的最短距离。
      再对反图求一遍spfa。求得其他顶点到1的最短距离。
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int inf = 0x3f3f3f3f;

const int N =  1000010;

typedef struct/*边表存储图*/
{
    int next,dis,e;
} Node;

typedef struct/*存储数据,方便处理反图*/
{
    int x,y,w;
} Line;

Line line[N];

int n,m;

Node edge[N];

int head[N],num_edge;

int dis[N];

int outqueue[N];

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


void bulid()
{
    memset(head,-1,sizeof(head));
    num_edge = 0;
    for(int i = 0 ; i < m ; i++)
    {
        addedge(line[i].x,line[i].y,line[i].w);
    }
}

bool spfa(int start)
{
    bool vis[N];
    memset(vis,false,sizeof(vis));
    memset(outqueue,0,sizeof(outqueue));
    memset(dis,0x3f,sizeof(dis));
    queue<int>q;
    vis[start] = true;
    q.push(start);
    dis[start] = 0;
    while(!q.empty())
    {
        int cur = q.front();
        q.pop();
        outqueue[cur]++;
        if(outqueue[cur] > n)
        {
            return false;
        }
        for(int i = head[cur] ; i != -1 ; i = edge[i].next)
        {
            if(dis[edge[i].e] > dis[cur] + edge[i].dis)
            {
                dis[edge[i].e] = dis[cur] + edge[i].dis;
            }
            if(!vis[edge[i].e])
            {
                vis[edge[i].e] = true;
                q.push(edge[i].e);
            }
        }
    }
    return true;
}



int main()
{
    long long ans;
    int ncase;
    scanf("%d",&ncase);
    while(ncase--)
    {
        ans = 0LL;
        scanf("%d %d",&n,&m);
        for(int i = 0 ; i < m ; i++)
        {
            scanf("%d %d %d",&line[i].x,&line[i].y,&line[i].w);
        }
        bulid();/*原图*/
        bool flag = spfa(1);
        if(flag)
        {
            for(int i = 1 ; i <= n ; i++)
            {
                ans += dis[i];
            }
        }
        for(int i = 0 ; i < m ; i++)/*反图*/
        {
            line[i].x = line[i].x^line[i].y;
            line[i].y = line[i].y^line[i].x;
            line[i].x = line[i].x^line[i].y;
        }
        bulid();
        flag = spfa(1);
        if(flag)
        {
            for(int i = 1 ; i <= n ; i++)
            {
               ans += dis[i];
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值