[关闭]
@sensitive-cs 2017-03-17T15:09:57.000000Z 字数 3149 阅读 707

CQUPT 最短路

题解


POJ 1125:STOCKBROKER GRAPEVINE
题意:
给出一幅有向图,计算出以哪个点为起点时,最大最短路距离最小。输出起点与距离。
思路:
迪杰斯特拉算法执行n次,需要注意的是判断某一点不可达时,是判断d[i]是否与inf相等。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int mmp[105][105];
  4. int vis[105];
  5. int d[105];
  6. const int inf = 100000000;
  7. int main()
  8. {
  9. int n;
  10. while (scanf("%d",&n) == 1 && n)
  11. {
  12. memset(mmp,0,sizeof(mmp));
  13. memset(d,0,sizeof(d));
  14. memset(vis,0,sizeof(vis));
  15. for (int i = 0;i < 105;i++)
  16. for (int j = 0;j < 105;j++)
  17. mmp[i][j] = inf;
  18. for (int i = 0;i < 105;i++)
  19. {
  20. mmp[i][i] = 0;
  21. d[i] = inf;
  22. }
  23. for (int i = 1;i <= n;i++)
  24. {
  25. int c;
  26. scanf("%d",&c);
  27. for (int j = 1;j <= c;j++)
  28. {
  29. int to,dis;
  30. scanf("%d%d",&to,&dis);
  31. mmp[i][to] = dis;
  32. }
  33. }
  34. int dissum = 0,mark = 0;
  35. int minn = inf;
  36. for (int i = 1;i <= n;i++)
  37. {
  38. int sumdis = 0;
  39. memset(vis,0,sizeof(vis));
  40. for (int j = 1;j <= n;j++)
  41. d[j] = inf;
  42. d[i] = 0;
  43. for (int j = 1;j <= n;j++)
  44. {
  45. int x,m = inf;
  46. for (int y = 1;y <= n;y++)
  47. if (!vis[y] && d[y] <= m) m = d[x=y];
  48. vis[x] = 1;
  49. for (int y = 1;y <= n;y++)
  50. if (d[y] > d[x] + mmp[x][y])
  51. d[y] = d[x] + mmp[x][y];
  52. }
  53. for (int j = 1;j <= n;j++)
  54. if (d[j] == inf)
  55. {
  56. dissum++;
  57. continue;
  58. }
  59. for (int j = 1;j <= n;j++)
  60. if (d[j] > sumdis)
  61. sumdis = d[j];
  62. if (sumdis < minn)
  63. {
  64. mark = i;
  65. minn = sumdis;
  66. }
  67. }
  68. if (dissum == n) printf("disjoint\n");
  69. else printf("%d %d\n",mark,minn);
  70. }
  71. return 0;
  72. }

poj 3259:WORMHOLES
题意:
给出一幅图,边权为正的边是双向的,边权为负的边是单向的,问是否存在负环。
思路:
bell-ford算法,这是一道(模版题。如果图中存在负环,则在算法执行过程中经过某一个点会超过1次。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. typedef struct edge
  4. {
  5. int s,e;
  6. int t;
  7. }edge;
  8. edge edg[5300];
  9. int d[505];
  10. int main()
  11. {
  12. int f;
  13. scanf("%d",&f);
  14. for (int o = 1;o <= f;o++)
  15. {
  16. int n,m,w;
  17. memset(edg,0,sizeof(edg));
  18. scanf("%d%d%d",&n,&m,&w);
  19. int sume = 0;
  20. for (int i = 0;i < m;i++)
  21. {
  22. int sta,sto,l;
  23. scanf("%d%d%d",&sta,&sto,&l);
  24. edg[sume].s = sta;
  25. edg[sume].e = sto;
  26. edg[sume].t = l;
  27. sume++;
  28. edg[sume].s = sto;
  29. edg[sume].e = sta;
  30. edg[sume].t = l;
  31. sume++;
  32. }
  33. for (int i = 0;i < w;i++)
  34. {
  35. int sta,sto,l;
  36. scanf("%d%d%d",&sta,&sto,&l);
  37. edg[sume].s = sta;
  38. edg[sume].e = sto;
  39. edg[sume].t = -l;
  40. sume++;
  41. }
  42. //printf("%d %d\n",w+m*2,sume);
  43. memset(d,0,sizeof(d));
  44. int flag = 0;
  45. for (int i = 0;i < n;i++)
  46. for (int j = 0;j < sume;j++)
  47. {
  48. edge tmp = edg[j];
  49. if (d[tmp.e] > d[tmp.s] + tmp.t)
  50. {
  51. d[tmp.e] = d[tmp.s] + tmp.t;
  52. if (i == n-1)
  53. flag = 1;
  54. }
  55. }
  56. if (flag) printf("YES\n");
  57. else printf("NO\n");
  58. }
  59. return 0;
  60. }

poj1026:昂贵的聘礼
题意:
中文题。
思路:
看了题解报告才写出来,菜!
原来卡住的地方是不知道如何使用这个等级,后来知道原来是在一个等级区间范围内的点可以进行最短路。
之后呢,就是如何表示等级区间啦,比如说,m为4,而酋长的等级为2的时候,等级区间就是1到5,2到6,就没有啦,因为必须包含酋长嘛,以此类推。之后就没有什么困难的啦,不过要改掉依赖模板的习惯。
坑:第一是自己把循环变量给用混了,神特么用混啊,思维不够严谨。第二呢是受题的样例的影响,觉得酋长的初始值一直都是10000,QAQ。
好的地方:一开始我觉得这题做不出来,好烦啊。但是后来静下心来思考之后,虽然借助了题解报告,但是还是把这道题给做出来了,看来做一切事情之前都要静下心来,才能做的好啊。
代码:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <algorithm>
  4. using namespace std;
  5. int g[105][105];
  6. int d[105];
  7. bool vis[105];
  8. int lev[105];
  9. int m,n;
  10. const int inf = 100000000;
  11. int dij(int l,int r)
  12. {
  13. memset(vis,0,sizeof(vis));
  14. for (int i = 0;i <= n;i++) d[i] = (i == 0 ? 0 : inf);
  15. lev[0] = l;
  16. for (int i = 0;i < n;i++)
  17. {
  18. int x,tmp = inf;
  19. for (int j = 0;j <= n;j++)
  20. {
  21. if (lev[j] >= l && lev[j] <= r)
  22. {
  23. if (!vis[j] && d[j] <= tmp)
  24. tmp = d[x = j];
  25. }
  26. }
  27. vis[x] = 1;
  28. for (int j = 0;j <= n;j++)
  29. {
  30. if (lev[j] >= l && lev[j] <= r)
  31. {
  32. d[j] = min(d[j],d[x] + g[x][j]);
  33. }
  34. }
  35. }
  36. return d[1];
  37. }
  38. int main()
  39. {
  40. while (scanf("%d%d",&m,&n) != EOF)
  41. {
  42. for (int i = 0;i < 105;i++)
  43. for (int j = 0;j < 105;j++)
  44. g[i][j] = 100000000;
  45. for (int i = 0;i < 105;i++) g[i][i] = 0;
  46. for (int i = 1;i <= n;i++)
  47. {
  48. int p,x;
  49. scanf("%d%d%d",&p,&lev[i],&x);
  50. g[0][i] = p;
  51. for (int j = 1;j <= x;j++)
  52. {
  53. int t,v;
  54. scanf("%d%d",&t,&v);
  55. g[t][i] = v;
  56. }
  57. }
  58. //printf("%d\n",g[4][1]);
  59. int ans = g[0][1];
  60. int l,r;
  61. if (lev[1] - m <= 0)
  62. {
  63. l = 1;
  64. r = l+m;
  65. }
  66. else
  67. {
  68. l = lev[1] - m;
  69. r = lev[1];
  70. }
  71. for (int i = 0;l + i <= lev[1];i++)
  72. {
  73. int tmp;
  74. tmp = dij(l+i,r+i);
  75. if (tmp < ans)
  76. ans = tmp;
  77. }
  78. printf("%d\n",ans);
  79. }
  80. return 0;
  81. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注