PKU 3259 Wormholes - 判断负权回路 Bellman-Ford

题目大意:

农场上有N块田地(N < = 500),M条路径(M <= 2500)可以从i到达j花费t单位时间。另外还有W个虫洞(W <= 200),虫洞可以从一块地i到达另一块地j并且时间倒退t!注意路径是双向的,虫洞是单向的。现在农夫John希望知道能否从某块地出发并且回到这块地,使得他回来的时间早于出发的时间(可以遇到他自己^^)。

分析:

褪去题目的伪装,可以看出,题目就是要求一个带负权的有向图中是否存在权值为负的回路

这个问题就是Bellman-Ford求带负权有向图的最短路径时,需要解决的问题。

 

  1. /*
  2. PKU3259 Wormholes
  3. */
  4. #include <stdio.h>
  5. #include <memory.h>
  6. #define clr(a) memset(a,0,sizeof(a))
  7. #define INF (1<<28)
  8. #define N 505
  9. #define M 6005
  10. int Bellman_Ford(int e[][3],int m,int n,int d[])
  11. {
  12.     int k,v,flag,i,j;
  13.     for(k=0;k<n;k++) d[k]=INF;
  14.     //d[0]=0;
  15.     for(k=0;k<n-1;k++)
  16.     {
  17.         flag=0;
  18.         for(v=0;v<m;v++){
  19.             i=e[v][0]; j=e[v][1];
  20.             if(d[j]>d[i]+e[v][2]){ 
  21.                 d[j]=d[i]+e[v][2];
  22.                 flag=1;
  23.             }
  24.         }
  25.         if(!flag) return 1;
  26.     }
  27.     for(v=0;v<m;v++)
  28.     if(d[e[v][1]]>d[e[v][0]]+e[v][2])
  29.         return 0;
  30.     return 1;
  31. }
  32. int n,m,w;
  33. int e[M][3],ne;
  34. int d[N];
  35. void addEdge(int i,int j,int k){
  36.     e[ne][0]=i;
  37.     e[ne][1]=j;
  38.     e[ne][2]=k;
  39.     ne++;
  40. }
  41. int main()
  42. {
  43.     int i,j,k,t,T;
  44.     
  45.     scanf("%d",&T);
  46.     while(T--){
  47.         //input
  48.         ne=0;
  49.         scanf("%d%d%d",&n,&m,&w);
  50.         for(k=0;k<m+w;k++){
  51.             scanf("%d%d%d",&i,&j,&t);
  52.             if(k<m){
  53.                 addEdge(i,j,t);
  54.                 addEdge(j,i,t);
  55.             }
  56.             else{
  57.                 addEdge(i,j,-t);
  58.             }
  59.         }
  60.         //output
  61.         if(Bellman_Ford(e,ne,n,d)) puts("NO");
  62.         else puts("YES");
  63.     }
  64.         
  65.     return 0;
  66. }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值