布局

  题目大意:有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[],M_Set[];
  17. static int dist[];
  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 = ; i < ML; i++)
  27. scanf("%d%d%d", &L_Set[i].A, &L_Set[i].B, &L_Set[i].cost);
  28. for (int i = ; 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 ;
  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[] = ;//到自己肯定是最短的
  39.  
  40. for (int i = ; i <= cows_sum; i++)
  41. {
  42. for (int i = ; i + <= cows_sum; i++)
  43. if (dist[i + ] < MAX)//差分约束方程d[i+1]>=d[i]
  44. dist[i] = min(dist[i], dist[i + ]);
  45. for (int i = ; 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 = ; 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[] < )
  55. printf("-1\n");
  56. else if (dist[cows_sum] == MAX)
  57. printf("-2\n");
  58. else printf("%d\n", 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[];//存边
  18. static Position Head[];
  19. static int dist[];
  20. static int out[];//记录出去多少次
  21. static bool used[];//记录是否在队内
  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, -, sizeof(Head)); memset(dist, 0x7f, sizeof(dist)); memset(used, , sizeof(used)); memset(out, , sizeof(out));
  32. edge_sum = ;
  33. //读入邻接表
  34. for (i = ; 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 = ; 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 = ; i + <= cows_sum; i++)//d[i+1]+0>=d[i]
  47. {
  48. edge[edge_sum].next = Head[i + ]; edge[edge_sum].to = i; edge[edge_sum].cost = ;
  49. Head[i + ] = edge_sum++;
  50. }
  51. SPFA(cows_sum, edge_sum);
  52. }
  53. return ;
  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(); dist[] = ; used[] = ;
  61.  
  62. while (!que.empty())
  63. {
  64. out_pos = que.front(); que.pop();
  65. used[out_pos] = ;//出队了就标记为0
  66. out[out_pos]++;
  67. if (out[out_pos] > cows_sum)
  68. {
  69. printf("-1\n");
  70. return;
  71. }
  72. for (int k = Head[out_pos]; k != -; 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] = ;
  81. que.push(to);
  82. }
  83. }
  84. }
  85. }
  86. if (dist[cows_sum] == MAX)
  87. printf("-2\n");
  88. else
  89. printf("%d\n", dist[cows_sum]);
  90. }

ShortestPath:Layout(POJ 3169)(差分约束的应用)的更多相关文章

  1. POJ - 3169 差分约束

    题意:n头牛,按照编号从左到右排列,两头牛可能在一起,接着有一些关系表示第a头牛与第b头牛相隔最多与最少的距离,最后求出第一头牛与最后一头牛的最大距离是多少,如         果最大距离无限大则输出 ...

  2. POJ 3169 Layout (spfa+差分约束)

    题目链接:http://poj.org/problem?id=3169 题目大意:n头牛,按编号1~n从左往右排列,可以多头牛站在同一个点,给出ml行条件,每行三个数a b c表示dis[b]-dis ...

  3. POJ 3169 Layout (图论-差分约束)

    Layout Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6574   Accepted: 3177 Descriptio ...

  4. poj 3159(差分约束经典题)

    题目链接:http://poj.org/problem?id=3159思路:题目意思很简单,都与给定的条件dist[b]-dist[a]<=c,求dist[n]-dist[1]的最大值,显然这是 ...

  5. [Usaco2005 dec]Layout 排队布局 差分约束

    填坑- 差分约束一般是搞一个不等式组,求xn-x1的最大最小值什么的,求最大值就转化成xa<=xb+w这样的,然后建图跑最短路(这才是最终约束的),举个例子 x1<=x0+2x2<= ...

  6. poj 1201 差分约束

    http://www.cnblogs.com/wangfang20/p/3196858.html 题意: 求集合Z中至少要包含多少个元素才能是每个区间[ai,bi]中的元素与Z中的元素重合个数为ci. ...

  7. BZOJ1731:[USACO]Layout 排队布局(差分约束)

    Description Like everyone else, cows like to stand close to their friends when queuing for feed. FJ ...

  8. bzoj 1731: [Usaco2005 dec]Layout 排队布局 ——差分约束

    Description 当排队等候喂食时,奶牛喜欢和它们的朋友站得靠近些.FJ有N(2<=N<=1000)头奶牛,编号从1到N,沿一条直线站着等候喂食.奶牛排在队伍中的顺序和它们的编号是相 ...

  9. bzoj 1731 [Usaco2005 dec]Layout 排队布局——差分约束

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1731 对差分约束理解更深.还发现美妙博客:http://www.cppblog.com/me ...

随机推荐

  1. 【BZOJ-2809】dispatching派遣 Splay + 启发式合并

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2334  Solved: 1192[Submi ...

  2. POJ1523 SPF

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 8254   Accepted: 3772 Description Consi ...

  3. POJ 1469 COURSES

    COURSES Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20478   Accepted: 8056 Descript ...

  4. (转)eclipse项目导入到android studio中

    原文:http://www.cnblogs.com/lao-liang/p/5016541.html?utm_source=tuicool&utm_medium=referral Androi ...

  5. EJB3 QL查询

    http://www.blogjava.net/liaojiyong/archive/2008/07/11/56216.html EJB3 QL查询 EJB3的查询语言是一种和SQL非常类似的中间性和 ...

  6. 提示用户一直输入数字(默认为正整数),当用户输入end的时候显示当前输入数字中的最大值。

    string input = ""; ; while (input != "end") { Console.WriteLine("请输入一个正整数,输 ...

  7. Laravel教程 六:表单 Forms

    Laravel教程 六:表单 Forms 此文章为原创文章,未经同意,禁止转载. Form laravel 5.2 之后请使用 laravelcollective/html 替换 illuminate ...

  8. WPF TabControl 模拟动画

    using System; using System.Threading; using System.Windows; using System.Windows.Controls; using Wan ...

  9. Windows下文件的所有和权限

    跟linux不同, 在linux下 ,文件的所有者,就拥有对文件的所有读写执行的权限, 而windows, 文件的所有者不一定对文件拥有所有的权限, 场景: 要对系统文件(windows\system ...

  10. Flume-NG中Transaction并发性探究

    我们曾经在Flume-NG中的Channel与Transaction关系(原创)这篇文章中说了channel和Transaction的关系,但是在source和sink中都会使用Transaction ...