POJ 1511 spfa求最短回路

http://poj.org/problem?id=1511

题意:(图论147)。求从起点到各个点的最短回路。

分析:用两次spfa就行了。第一次spfa是从出发点start到各个点,求一次最短距离,第二次spfa是从各个点反向求到出发点的最短距离。

处理:第一次spfa只要保存正向边,第二次用反向边进行spfa就可以了。最后把两次求得的距离相加就是最短回路。

View Code
// I'm the Topcoder
//C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
//C++
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cctype>
#include <stack>
#include <string>
#include <list>
#include <queue>
#include <map>
#include <vector>
#include <deque>
#include <set>
using namespace std;

//*************************OUTPUT*************************
#ifdef WIN32
#define INT64 "%I64d"
#define UINT64 "%I64u"
#else
#define INT64 "%lld"
#define UINT64 "%llu"
#endif

//**************************CONSTANT***********************
#define INF 0x3f3f3f3f
#define eps 1e-8
#define PI acos(-1.)
#define PI2 asin (1.);
typedef long long LL;
//typedef __int64 LL;   //codeforces
typedef unsigned int ui;
typedef unsigned long long ui64;
#define MP make_pair
typedef vector<int> VI;
typedef pair<int, int> PII;
#define pb push_back
#define mp make_pair

//***************************SENTENCE************************
#define CL(a,b) memset (a, b, sizeof (a))
#define sqr(a,b) sqrt ((double)(a)*(a) + (double)(b)*(b))
#define sqr3(a,b,c) sqrt((double)(a)*(a) + (double)(b)*(b) + (double)(c)*(c))

//****************************FUNCTION************************
template <typename T> double DIS(T va, T vb) { return sqr(va.x - vb.x, va.y - vb.y); }
template <class T> inline T INTEGER_LEN(T v) { int len = 1; while (v /= 10) ++len; return len; }
template <typename T> inline T square(T va, T vb) { return va * va + vb * vb; }

// aply for the memory of the stack
//#pragma comment (linker, "/STACK:1024000000,1024000000")
//end

const int maxn = 1000000+100;
struct node{
    int to;
    int next;
    long long weight;
};
node edge[maxn],edge1[maxn];//保存边的起点和终点
int n,m;
long long val;
int tot,tot1;
int src;//起点
int head[maxn],head1[maxn];
int visit[maxn],visit1[maxn];
long long dis[maxn],dis1[maxn];

void add(int a,int b,long long c){
    edge[tot].to=b;
    edge[tot].weight=c;
    edge[tot].next=head[a];
    head[a]=tot++;
}

void add1(int a,int b,long long c){
    edge1[tot1].to=b;
    edge1[tot1].weight=c;
    edge1[tot1].next=head1[a];
    head1[a]=tot1++;
}

void spfa(){
    //初始化
    for(int i=1;i<=n;i++){
        dis[i]=INF;
        visit[i]=0;//访问标记
    }
    dis[src]=0; visit[src]=1;
    int u;
    int v;
    queue<int> Q;//优先队列
    Q.push(src);
    while(!Q.empty()){
        u=Q.front();
        Q.pop();
         visit[u]=0;//必须是0,这题是1也能过不过是错的
       // visit[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next){
            v=edge[i].to;
            if(dis[v]>dis[u]+edge[i].weight){
                dis[v]=dis[u]+edge[i].weight;
                if(!visit[v]){
                    Q.push(v);
                    visit[v]=1;
                }
            }
        }
    }
}


void spfa1(){
    //初始化
    for(int i=1;i<=n;i++){
        dis1[i]=INF;  visit1[i]=0;
    }
    dis1[src]=0;  visit1[src]=1;
    int u,v;
    queue<int> Q;
    Q.push(src);
    while(!Q.empty()){
        u=Q.front();
        Q.pop();
         visit[u]=0;//必须是0,这题是1也能过不过是错的
        //visit1[u]=1;
        for(int i=head1[u];i!=-1;i=edge1[i].next){
            v=edge1[i].to;
            if(dis1[v]>dis1[u]+edge1[i].weight){
                dis1[v]=dis1[u]+edge1[i].weight;
                if(!visit1[v]){
                    Q.push(v);
                    visit1[v]=1;
                }
            }
        }
    }
}

int main(){
    int a,b,cas;
    scanf("%d",&cas);
    while(cas--){
        scanf("%d%d",&n,&m);
        tot=tot1=0;//边的条数
        for(int i=1;i<=n;i++){
            head[i]=-1;
            head1[i]=-1;
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d%lld",&a,&b,&val);
            add(a,b,val);//正向边
            add1(b,a,val);//反向边
        }
        src=1;//起点(终点)
        spfa();
        spfa1();
        long long sum=0;
        for(int i=2;i<=n;i++){
            sum+=dis[i]+dis1[i];
        }
        printf("%lld\n",sum);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值