• poj 3259 时光穿梭问题 bellman_ford算法


    题意:有n个空地,有m条双向大路,w条时光隧道单向路。问能否回到过去?

    思路:判断是否有负环存在,如果有负环存在那么就可以一直小就可以回到过去了

    1. 创建源顶点 V到其他顶点的距离d 初始为INF d[1]=0;
    2. 计算最路径,执行v-1次遍历  对于每条边 if(d[v]>d[s]+t)  d[v]=d[s]+t;
    3. 判断是否有负环   遍历所有的边 计算u至v的距离,如果对于v存在更小的距离 则存在 
    4. 有松弛 d[v]>d[u]+t 

    解决问题的代码:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define maxn 510
    #define maxw 2550*2+510
    #define INF 1000000
    int d[maxn];
    int n, m;
    struct node {
            int u, v;
            int t;
    }edge[maxw];
    bool solve()
    {
            for (int i = 1; i <=n; i++) d[i] = INF;
            d[1] = 0;
            for (int i = 1; i < n; i++)
            {
                   bool flag = true;
                   for (int j = 0; j < m; j++)
                   {
                           int u = edge[j].u;
                           int v = edge[j].v;
                           int t = edge[j].t;
                           if (d[v] > d[u] + t)
                           {
                                  d[v] = d[u] + t;
                                  flag = false;
                           }
                   }
                   if (flag) return false;
            }
            for (int i = 0; i < m; i++)
            {
                   if (d[edge[i].v] > d[edge[i].u] + edge[i].t)
                           return true;
            }
            return false;
    }
    int main()
    {
            int t;
            scanf("%d", &t);
            while (t--)
            {
                   int M, W;
                   scanf("%d%d%d",&n, &M, &W);
                   m = 0;
                   for (int i = 1; i <= M; i++)
                   {
                           int u, v, t;
                           scanf("%d%d%d", &u, &v, &t);
                           edge[m].u = u;
                           edge[m].v = v;
                           edge[m++].t = t;
                           edge[m].u = v;
                           edge[m].v = u;
                           edge[m++].t = t;
                   }
                   for (int i =1; i <= W; i++)
                   {
                           int u, v, t;
                           scanf("%d%d%d", &u, &v, &t);
                           edge[m].u = u;
                           edge[m].v = v;
                           edge[m].t = -t;
                   }
                   if (solve()) printf("YES
    ");
                   else printf("NO
    ");
            }
            return 0;
    }

    其中比较神奇的是存图技巧

    君子知命不惧,自当日日自新
  • 相关阅读:
    [转]OLAP的12条准则
    这几年
    方法论
    用NetHogs监控Linux每个进程的网络使用情况
    Centos下文本文件格式转码解决
    CentOS+Puppet分布式部署Zabbix监控系统
    ubuntu修复grub,u盘引导问题
    postfix搭建纯邮件转发服务器
    Mysql: 利用强制索引去掉重数据
    shell 变量赋值与替换
  • 原文地址:https://www.cnblogs.com/xuxiaojin/p/9407846.html
Copyright © 2020-2023  润新知