zoukankan      html  css  js  c++  java
  • ShortestPath:Layout(POJ 3169)(差分约束的应用)

                         

                            布局

      题目大意:有N头牛,编号1-N,按编号排成一排准备吃东西,有些牛的关系比较好,所以希望他们不超过一定的距离,也有一些牛的关系很不好,所以希望彼此之间要满足某个关系,牛可以挤在同一个位置上,现在给出N个牛的信息,问你能否实现一种排列方案,使得d[1]到d[N]最大?如果不存在输出-1,无限大输出-2

      这一题看上去挺难的,但是如果你知道差分约束原理,这一题似乎还是挺简单的。

      差分约束的原理是:存在任意线性方程,满足d[A]+c>=d[B],就可以表示为图的最短路形式,方程可以表示为A->B,权值为c的边,最后任意点之间距离之差的最大值,即为两点之间的最短距离。

      在最短路的算法中,恒有d[u]+w>=d[s](s是源点,w是权值,u是除了s的任意点),则d[u]-d[s]的最大值即为s-u的最短路经长。

      回到题目上来,那么这一题事实上蕴含了三个线性方程:

        1.d[i+1]>=d[i](按照编号排序)

        2.d[BL]-d[AL]<=DL->->->d[AL]+DL>=d[BL]

        3.d[BD]-D[AD]>=DD->->->d[BD]-DD>=d[AD]

        则我们只用把这些边表示出来算最短路径就可以了,这一题有负值边,用Bellman_Ford或者SPFA就可以了

      

    Bellman_Ford:

     1 #include <iostream>
     2 #include <functional>
     3 #include <algorithm>
     4 #define MAX 0x7f7f7f7f
     5 
     6 using namespace std;
     7 
     8 typedef int Positon;
     9 typedef struct least_
    10 {
    11     Positon A;
    12     Positon B;
    13     int cost;
    14 }Relation;
    15 
    16 static Relation L_Set[1000005],M_Set[1000005];
    17 static int dist[1005];
    18 
    19 void Bellman_Ford(const int, const int, const int);
    20 
    21 int main(void)
    22 {
    23     int cows_sum, ML, MD;
    24     while (~scanf("%d%d%d", &cows_sum, &ML, &MD))
    25     {
    26         for (int i = 0; i < ML; i++)
    27             scanf("%d%d%d", &L_Set[i].A, &L_Set[i].B, &L_Set[i].cost);
    28         for (int i = 0; i < MD; i++)
    29             scanf("%d%d%d", &M_Set[i].A, &M_Set[i].B, &M_Set[i].cost);
    30         Bellman_Ford(cows_sum, ML, MD);
    31     }
    32     return 0;
    33 }
    34 
    35 void Bellman_Ford(const int cows_sum, const int ML, const int MD)
    36 {
    37     memset(dist, 0x7f, sizeof(dist));
    38     dist[1] = 0;//到自己肯定是最短的
    39 
    40     for (int i = 1; i <= cows_sum; i++)
    41     {
    42         for (int i = 1; i + 1 <= cows_sum; i++)
    43             if (dist[i + 1] < MAX)//差分约束方程d[i+1]>=d[i]
    44                 dist[i] = min(dist[i], dist[i + 1]);
    45         for (int i = 0; i < ML; i++)//差分约束方程d[AL]+DL>=d[BL]
    46             if (dist[L_Set[i].A] < MAX)
    47                 dist[L_Set[i].B] = min(dist[L_Set[i].B], dist[L_Set[i].A] + L_Set[i].cost);
    48         for (int i = 0; i < MD; i++)//差分约束方程d[BD]-DD>=d[AD]
    49             if (dist[M_Set[i].B] < MAX)
    50                 dist[M_Set[i].A] = min(dist[M_Set[i].A], dist[M_Set[i].B] - M_Set[i].cost);
    51     }
    52 
    53     int ans = dist[cows_sum];
    54     if (dist[1] < 0)
    55         printf("-1
    ");
    56     else if (dist[cows_sum] == MAX)
    57         printf("-2
    ");
    58     else printf("%d
    ", ans);
    59 }

    SPFA:

     1 #include <iostream>
     2 #include <functional>
     3 #include <algorithm>
     4 #include <queue>
     5 #define MAX 0x7f7f7f7f
     6 
     7 using namespace std;
     8 
     9 typedef int Position;
    10 typedef struct least_
    11 {
    12     int next;
    13     Position to;
    14     int cost;
    15 }Edge_Set;
    16 
    17 static Edge_Set edge[2000010];//存边
    18 static Position Head[1005];
    19 static int dist[1005];
    20 static int out[1005];//记录出去多少次
    21 static bool used[1005];//记录是否在队内
    22 
    23 void SPFA(const int, const int);
    24 
    25 int main(void)
    26 {
    27     int cows_sum, ML, MD, i, cost, edge_sum;
    28     Position from, to;
    29     while (~scanf("%d%d%d", &cows_sum, &ML, &MD))
    30     {
    31         memset(Head, -1, sizeof(Head)); memset(dist, 0x7f, sizeof(dist)); memset(used, 0, sizeof(used)); memset(out, 0, sizeof(out));
    32         edge_sum = 0;
    33         //读入邻接表
    34         for (i = 0; i < ML; i++)//d[BL]-d[AL]<=DL->->->d[AL]+DL>=d[BL]
    35         {
    36             scanf("%d%d%d", &from, &to, &cost);//因为编号是有序的,所以只用储存单向边就可以了
    37             edge[edge_sum].next = Head[from]; edge[edge_sum].to = to; edge[edge_sum].cost = cost;
    38             Head[from] = edge_sum++;
    39         }
    40         for (i = 0; i < MD; i++)//d[BL]-d[AL]>=DL->->->d[BD]-DD>=d[AD]
    41         {
    42             scanf("%d%d%d", &from, &to, &cost);
    43             edge[edge_sum].next = Head[to]; edge[edge_sum].to = from; edge[edge_sum].cost = -cost;
    44             Head[to] = edge_sum++;
    45         }
    46         for (i = 1; i + 1 <= cows_sum; i++)//d[i+1]+0>=d[i]
    47         {
    48             edge[edge_sum].next = Head[i + 1]; edge[edge_sum].to = i; edge[edge_sum].cost = 0;
    49             Head[i + 1] = edge_sum++;
    50         }
    51         SPFA(cows_sum, edge_sum);
    52     }
    53     return 0;
    54 }
    55 
    56 void SPFA(const int cows_sum, const int edge_sum)//这次用STL玩玩
    57 {
    58     Position out_pos, to;
    59     queue<Position>que;
    60     que.push(1); dist[1] = 0; used[1] = 1;
    61 
    62     while (!que.empty())
    63     {
    64         out_pos = que.front(); que.pop();
    65         used[out_pos] = 0;//出队了就标记为0
    66         out[out_pos]++;
    67         if (out[out_pos] > cows_sum)
    68         {
    69             printf("-1
    ");
    70             return;
    71         }
    72         for (int k = Head[out_pos]; k != -1; k = edge[k].next)
    73         {
    74             to = edge[k].to;
    75             if (dist[to] > dist[out_pos] + edge[k].cost)
    76             {
    77                 dist[to] = dist[out_pos] + edge[k].cost;
    78                 if (!used[to])
    79                 {
    80                     used[to] = 1;
    81                     que.push(to);
    82                 }
    83             }
    84         }
    85     }
    86     if (dist[cows_sum] == MAX)
    87         printf("-2
    ");
    88     else
    89         printf("%d
    ", dist[cows_sum]);
    90 }

  • 相关阅读:
    使用phantomjs进行刷商务通对话
    利用python打造自己的ftp暴力破解工具
    notepad++开发中常用的插件
    织梦重装漏洞其实并不是那么好利用
    织梦开启调试模式
    网站安全开发人员不可缺少的火狐插件
    dos批量替换当前目录后缀名
    wpf 帧动画
    C 语言 mmap
    C 语言 ioctl
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4951640.html
Copyright © 2011-2022 走看看