poj 3268 简单的SPFA算法运用

题目关键在于: 存储图的正向和反向两种形式 , 然后分别求点x 到其他的的最短路径长度 , 这就等于求到了点x 到其他点的最短路径和其他点到x的最短路径长度。

代码:
#include
#include
#include
#include
using namespace std;

#define maxn 1110
#define INF 0xfffffff
struct node  //数组模拟邻接表
{
      int to;
      int w;
      int next;
}edge[maxn*maxn];

struct node1  //数组模拟邻接表
{
      int to;
      int w;
      int next;
}fedge[maxn*maxn];

int n , m , x0;
int pre[maxn];
int dist[maxn];
int fdist[maxn];
int next[maxn];
int fnext[maxn];

void init()
{
      memset(next , -1 , sizeof(next));
      memset(fnext , -1 , sizeof(fnext));
      memset(pre , 0 , sizeof(pre));
}

bool spfa(int u)
{
      queueq;
      q.push(u);

      int i , vis[maxn];
      memset(vis , 0 , sizeof(vis));

      for(i = 1; i <= n; i++)
            dist[i] = INF;

      dist[u] = 0; //一定要记得对于源点的初始化
      vis[u] += 1;

      while(!q.empty())
      {
            int v = q.front(); q.pop();
            pre[v] = 0;

            for(i = next[v] ; i != -1; i = edge[i].next)
            {
                  int x = edge[i].to , w = edge[i].w;
                  if(dist[x] > dist[v]+w)
                  {
                        dist[x] = dist[v]+w;
                        if(!pre[x] && ++vis[x] > n)  return false;  //判断是否存在负环
                        if(!pre[x])  q.push(x) , pre[x] = 1;
                  }
            }
      }

      return true;
}

bool fspfa(int u)
{
      queueq;
      q.push(u);

      int i , vis[maxn];
      memset(vis , 0 , sizeof(vis));
      memset(pre , 0 , sizeof(pre));

      for(i = 1; i <= n; i++)
            fdist[i] = INF;

      fdist[u] = 0; //一定要记得对于源点的初始化
      vis[u] += 1;

      while(!q.empty())
      {
            int v = q.front(); q.pop();
            pre[v] = 0;

            for(i = fnext[v] ; i != -1; i = fedge[i].next)
            {
                  int x = fedge[i].to , w = fedge[i].w;
                  if(fdist[x] > fdist[v]+w)
                  {
                        fdist[x] = fdist[v]+w;
                        if(!pre[x] && ++vis[x] > n)  return false;  //判断是否存在负环
                        if(!pre[x])  q.push(x) , pre[x] = 1;
                  }
            }
      }

      return true;
}

int main()
{
      while(scanf("%d %d %d" , &n , &m , &x0) != EOF)
      {
            init();
            int i , x , y , z , k = 0 , t = 0;
            for(i = 0; i < m; i++)
            {
                  scanf("%d %d %d" , &x , &y , &z);
                  edge[k].to = y;
                  edge[k].w = z;
                  edge[k++].next = next[x];
                  next[x] = k-1;
                 
                  fedge[t].to = x;
                  fedge[t].w = z;
                  fedge[t++].next = fnext[y];
                  fnext[y] = k-1;
            }
            spfa(x0);
            fspfa(x0);
            int maxsum = 0;
            for(i = 1; i <= n; i++)
                  //cout<<dist[i]<<","<<fdist[i]<<endl;
                  if(dist[i]+fdist[i] > maxsum )  maxsum = dist[i]+fdist[i];
                 
            cout<<maxsum<<endl;
                  //      bool xy = spfa(1);
      }
      return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值