• POJ Wormholes 最短路径 ballman_ ford 有负环


     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <iostream>
     5 #include <queue>
     6 #define MAX 9999999
     7 
     8 using namespace std;
     9 
    10 struct node
    11 {
    12     int u, v, w;//u 为起点,v为终点,w为u—>v的权值
    13 };
    14 node edge[5203];
    15 int n, m;//n 点数   m 边数
    16 
    17 bool bellman_ford()
    18 {
    19     int i, j;
    20     bool flag;
    21     int dis[503];//保存最短路径
    22 
    23     fill(dis,dis+n,MAX);//初始化
    24     dis[1] = 0;//因为判断是否有负环,对整个图而言,So  s = 1;
    25     //
    26     for(i=1;i<n;i++)//共需进行|V|-1次
    27     {
    28         flag = false;//优化   初始化为假
    29         for(j=0;j<m;j++)//对每一条边
    30         {
    31             // if  u.d>v.d+w(u,v) , u.d = v.d+w(u,v);
    32             if(dis[edge[j].u]>dis[edge[j].v]+edge[j].w){//进行松弛
    33                 dis[edge[j].u] = dis[edge[j].v]+edge[j].w;//松弛操作成功
    34                 flag = true;//松弛成功变为真
    35             }
    36         }
    37         if(!flag)//若每条边没有松弛
    38             break;//跳出循环
    39     }
    40     // 
    41     for(i=0;i<m;i++)
    42         if(dis[edge[i].u]>dis[edge[i].v]+edge[i].w)//进行|V|-1次操作后  有边还能进行松弛  说明
    43             return true;//存在负环
    44     return false;//不存在负环
    45 }
    46 
    47 int main()
    48 {
    49     int t, k, i;
    50 
    51     scanf("%d",&t);//输入测试数据的组数
    52     while(t-- && scanf("%d %d %d",&n,&m,&k)){//输入点数,正边数,负边数
    53         for(i=0;i<m;i++)
    54         {
    55             scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);//输入u,v,w;
    56             edge[i+m].u = edge[i].v;//双向
    57             edge[i+m].v = edge[i].u;//双向
    58             edge[i+m].w = edge[i].w;//双向
    59         }
    60         m <<= 1;//正边为双向 所以m = m*2;
    61         for(i=m;i<m+k;i++)
    62         {
    63             scanf("%d %d %d",&edge[i].u,&edge[i].v,&edge[i].w);//存负边数(单向)
    64             edge[i].w = -edge[i].w;//负边就要是负的
    65         }
    66         m += k;//单向,So不需要*2
    67         printf("%s
    ",bellman_ford()?"YES":"NO");//输出结果
    68     }
    69     return 0;
    70 }
    View Code

    题目大意: 第一行 输入一个数  是表示几组测试数据

        第二行  三个数 N(点的个数),M(正边的个数),W(负边的个数) 注意 :正边为双向的,负边为单向的。

        然后 M行u,v,w;

        再然后W行u,v,w;

        求这个图是不是存在负环。 有 YES 没NO。

    若没有负环外循环最多进行|V|-1次即可,就可得到最短路径,那么若存在负环,则第|V|次操作还改变D数组,则有负环。

    负环即回路中权值相加为负数。   如果陷入负环中,环中的顶点最短路径就会陷入死循环,无限变小,不会停下。。。

    这题废物了我两天,不过也值了。O(∩_∩)O~。。

  • 相关阅读:
    第一个java程序 Hello,World
    安装jdk,配置环境变量
    QQ传输大文件,服务器拒绝了你发送离线文件
    在WPF显示动态GIF图片
    Windows下预览svg
    WPF,ScrollViewer的属性VerticalScrollBarVisibility、HorizontalScrollBarVisibility值的区别
    未能添加对“*.dll”的引用
    端口被占用
    windows下安装tomcat
    编译安装Linux内核 centos版本
  • 原文地址:https://www.cnblogs.com/WDKER/p/5172342.html
Copyright © 2020-2023  润新知