• 【图论】求最长路径


     知识点

    Dijkstra算法不能求最长路径 ,常使用SPFA

    经典Dijkstra算法根据贪心思想,每次通过所在的点路径最短的路径来松弛其他点,并且保证了这个操作每个点只会进行一次(除了距离最远的点,因为最后一点被松弛完整个算法就结束了),但是,求最长路径的时候不能保证在当前所经过的路径最长,最后的总长也最长,即最优子结构无法满足整体最优 。

    这时候就需要使用动态规划了,而SPFA算法就是基于动态规划而形成的算法


     例题:洛谷 P1807 最长路

    题目描述

    设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 G 中 1, n 间的最长路径。

    输入格式

    输入的第一行有两个整数,分别代表图的点数 n 和边数 m。

    第 2 到第 (m + 1) 行,每行 33 个整数 u,v,w(u

    输出格式

    输出一行一个整数,代表 1 到 n 的最长路。

    若 1 与 n 不连通,请输出 −1。

    输入输出样例

    输入 #1

    2 1
    1 2 1

    输出 #1

    1

    说明/提示

    【数据规模与约定】

    • 对于 20%的数据,n≤100,m≤10^3。
    • 对于 40% 的数据,n≤10^3,m≤10^4。
    • 对于 100% 的数据,1≤n≤1500,1≤m≤5×10^4,1≤u,v≤n,-10^5 ≤w≤10^5。

     ① 使用经典Dijkstra算法 (56pts)

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. int n,m;
    9. const int maxn=1e7+5;
    10. struct node
    11. {
    12. int to,next,w;
    13. }edge[maxn<<1];
    14. int head[maxn],dis[maxn],ans[maxn],num=0;
    15. bool vis[maxn];
    16. struct node1{
    17. int ans,id;
    18. bool operator <(const node1&x) const
    19. {
    20. return x.ans > ans;
    21. }
    22. };
    23. priority_queue q;
    24. inline int read()
    25. {
    26. int x=0,f=1;
    27. char c=getchar();
    28. while(c<'0'||c>'9')
    29. {
    30. if(c=='-') f=-1;
    31. c=getchar();
    32. }
    33. while(c>='0'&&c<='9')
    34. {
    35. x=(x<<3)+(x<<1)+(c^48);
    36. c=getchar();
    37. }
    38. return x*f;
    39. }
    40. inline void write(int x)
    41. {
    42. if(x<0) putchar('-'),x=-x;
    43. if(x>9) write(x/10);
    44. putchar(x%10+'0');
    45. }
    46. inline void add(int u,int v,int w)
    47. {
    48. edge[++num].to=v;
    49. edge[num].w=w;
    50. edge[num].next=head[u];
    51. head[u]=num;
    52. }
    53. inline void dij()
    54. {
    55. int u;
    56. dis[1]=0;
    57. q.push((node1){0,1});
    58. while(!q.empty())
    59. {
    60. node1 temp=q.top();
    61. u=temp.id;
    62. q.pop();
    63. if(vis[u]) continue;
    64. vis[u]=true;
    65. for(int i=head[u];i!=-1;i=edge[i].next)
    66. {
    67. int v=edge[i].to;
    68. if(dis[v]//将大于号改为小于号
    69. {
    70. dis[v]=dis[u]+edge[i].w;
    71. if(!vis[v]) q.push((node1){dis[v],v});
    72. }
    73. }
    74. }
    75. }
    76. int main()
    77. {
    78. n=read(); m=read();
    79. memset(head,-1,sizeof(head));
    80. memset(dis,-1,sizeof(dis)); //dis[]设为-1,相当于平日MAX=-999999999
    81. for(int i=1;i<=m;++i)
    82. {
    83. int u=read(),v=read(),w=read();
    84. add(u,v,w);
    85. }
    86. dij();
    87. write(dis[n]);
    88. return 0;
    89. }

     ②  已AC代码:(只去掉了vis[ ] 的判断)

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. using namespace std;
    8. int n,m;
    9. const int maxn=1e7+5;
    10. struct node
    11. {
    12. int to,next,w;
    13. }edge[maxn<<1];
    14. int head[maxn],dis[maxn],num=0;
    15. bool vis[maxn];
    16. struct node1{
    17. int ans,id;
    18. bool operator <(const node1&x) const
    19. {
    20. return x.ans > ans;
    21. }
    22. };
    23. priority_queue q;
    24. inline int read()
    25. {
    26. int x=0,f=1;
    27. char c=getchar();
    28. while(c<'0'||c>'9')
    29. {
    30. if(c=='-') f=-1;
    31. c=getchar();
    32. }
    33. while(c>='0'&&c<='9')
    34. {
    35. x=(x<<3)+(x<<1)+(c^48);
    36. c=getchar();
    37. }
    38. return x*f;
    39. }
    40. inline void write(int x)
    41. {
    42. if(x<0) putchar('-'),x=-x;
    43. if(x>9) write(x/10);
    44. putchar(x%10+'0');
    45. }
    46. inline void add(int u,int v,int w)
    47. {
    48. edge[++num].to=v;
    49. edge[num].w=w;
    50. edge[num].next=head[u];
    51. head[u]=num;
    52. }
    53. inline void dij()
    54. {
    55. int u;
    56. dis[1]=0;
    57. q.push((node1){0,1});
    58. while(!q.empty())
    59. {
    60. node1 temp=q.top();
    61. u=temp.id;
    62. q.pop();
    63. //去掉了vis[]的判断
    64. for(int i=head[u];i!=-1;i=edge[i].next)
    65. {
    66. int v=edge[i].to;
    67. if(dis[v]
    68. {
    69. dis[v]=dis[u]+edge[i].w;
    70. q.push((node1){dis[v],v});
    71. }
    72. }
    73. }
    74. }
    75. int main()
    76. {
    77. n=read(); m=read();
    78. memset(head,-1,sizeof(head));
    79. memset(dis,-1,sizeof(dis));
    80. for(int i=1;i<=m;++i)
    81. {
    82. int u=read(),v=read(),w=read();
    83. add(u,v,w);
    84. }
    85. dij();
    86. write(dis[n]);
    87. return 0;
    88. }

  • 相关阅读:
    volatile原理解析
    win10 sourcetree打开一闪就退出
    Java集合框架(二)Set
    LeetCode题-回文数-2023/9/11
    Linux学习第13天:嵌入式LinuxLED驱动开发:一字一符总见情
    redis集群的安装部署
    向新而生保业务增长,亚信科技持续锻造“核心引擎”
    JMeter--监听器--聚合报告
    完美校园电费不足时推送消息
    使用acme.sh申请免费ssl证书(Cloudflare方式API自动验证增加DNS Record到期证书到期自动重新申请)
  • 原文地址:https://blog.csdn.net/gzkeylucky/article/details/124649612