poj2679  最短路+受负环影响点的判…

 

解题报告

题目 http://poj.org/problem?id=2679

题目大意 :给定一个图,每条边有两个值长度和费用。求AB的最少花费路且路程尽量短,要求从AB的最短路中所使用的路,都是某节点的最短出边,设A->C->d>B.那么a->c

就是a的所有出边中最短的(花费边),

算法 SPFA + 深搜判点是否受影响。

思路 :把每个点的出边在建图时只保留最短边,这个用链表在建图时就很容易能搞定。然后在这个图上,用SPFA求最短路,条件是if(times[u] > n + 5) return 0来判负环。而这个题的难处在于我们也要确定的是在AB这条路径上有没有环,也就是判断B受不受负环影响,而不是图整体有没有环,利用times值,如果一个点在环上,必有times[p] > n 那么。我们枚举每个点,如果times[p] >n而且pB有路(深搜一下就能判断)。那么说明AB是有负环的。

提交情况 wrong answ 5 理解错题意

           Time limit error 4 方法不对

           Accrpted 一次
经验与收获 :有一次发现自己经常使用的SPFA其实并不是理解的很好,比如说当我们用队列实现的时候,那么我们能够很快的判断出负环,但是不能将所有点最起码的最短路求出来。而队列实现的SPFA能够确保我们为负环外的点找到一条很短的路,这样有助于我们进行其他操作。本题就需要队列,而且,spfa中的times不是仅仅能够判断负环,而且能够标记一个点是不是在负环上(至少能证明一个点可能在负环上)。这样我们能够利用这个信息处理一个点B是否受负环影响,只要从负环上的点开始深搜,看能否到达B即可。

AC code

#include <stdio.h>

#include <string.h>

 

#define MAXN 2210

#define MAXM 11000

#define INF 0x33333333

 

struct NODE{

    int to, len, cost, next;

} edges[MAXM];

inthead[MAXN], ad, n, m, A, B, T;

intcost[MAXN], path[MAXN];

 

voidclear(){

    ad = 0;

    memset(head, -1, sizeof(head));

}

 

void insert(int u, int v, int cost, int len){

    if(head[u] != -1 && cost > edges[head[u]].cost) return;

    if(head[u] != -1 && cost < edges[head[u]].cost) head[u] = -1;

    edges[ad].to = v; edges[ad].cost = cost; edges[ad].len = len; edges[ad].next = head[u]; head[u] = ad ++;

}

 

intqueue[MAXN], in[MAXN], times[MAXN];

int SPFA(int A){

    int front = 0, tail = 1;

    memset(cost, 0x33, sizeof(cost));

    memset(path, 0x33, sizeof(path));

    memset(in, 0, sizeof(in));

    memset(times, 0, sizeof(times));

    queue[front] = A;

    cost[A] = path[A] = 0;

    in[A] = times[A] = 1;

    while(front != tail){

       int u = queue[front], v;

       front = (front + 1) % MAXN;

       in[u] = 0;

       if(times[u] > n + 5) return 0;

       for(int p = head[u]; ~p; p = edges[p].next){

           v = edges[p].to;

           if((cost[v] > cost[u] + edges[p].cost) || ((cost[v] == cost[u] + edges[p].cost) && (path[v] > path[u] + edges[p].len))){

              cost[v] = cost[u] + edges[p].cost;

              path[v] = path[u] + edges[p].len;

              if(!in[v]){

                  queue[tail] = v;

                  tail = (tail + 1) % MAXN;

                  in[v] = 1;

                  times[v] ++;

              }

           }

       }

    }

    return 1;

}

 

 

void dfs(int u){

    in[u] = 1;

    if(u == B){ T = 1; return;}

    for(int p = head[u]; ~p; p = edges[p].next){

       if(!in[edges[p].to]) dfs(edges[p].to);

    }

}

 

int main(){

    int i, j, u, v, fuv, fvu, len, falg;

    char ch;

    while(~scanf("%d %d %d %d", &n, &m, &A, &B)){

       clear();

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

           while(scanf("%c", &ch), ch != '(');

           scanf("%d,%d,%d[%d]%d)", &u, &v, &fuv, &len, &fvu);

           insert(u, v, fuv, len);

           insert(v, u, fvu, len);

       }

       falg = SPFA(A);

       if(cost[B] == INF) printf("VOID\n");

       else

           if(falg) printf("%d %d\n", cost[B], path[B]);

           else{

              for(i = 0; i < n; i ++){

                  if(times[i] > n){

                     memset(in, 0, sizeof(in));

                     T = 0;

                     dfs(i);

                     if(T) break;

                  }

              }

              if(T || times[B] > n) printf("UNBOUND\n");

              else printf("%d %d\n", cost[B], path[B]);

           }

    }

    return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值