• P1339 热浪 最短路径模板题


    新模板

     1 void dijkstra(int s) {
     2     std::priority_queue<Node> Q;
     3     memset(dis + 1, 0x3f, (n + 1) * sizeof(LL));
     4     dis[s] = 0;
     5     Q.push(Node(s, dis[s]));
     6     while(!Q.empty()) {
     7         while(!Q.empty() && dis[Q.top().x] != Q.top().dis) {
     8             Q.pop();
     9         }
    10         if(Q.empty()) {
    11             break;
    12         }
    13         int x = Q.top().x;
    14         Q.pop();
    15         for(int i = e[x]; i; i = edge[i].nex) {
    16             int y = edge[i].v;
    17             if(dis[y] > dis[x] + edge[i].len) {
    18                 dis[y] = dis[x] + edge[i].len;
    19                 Q.push(Node(y, dis[y]));
    20             }
    21         }
    22     }
    23     return;
    24 }
    Dijkstra

    这么naive的题面一看就是最短路模板题~~~

    ok。首先是floyd算法,tts(Too yo*ng Too s*mple Sometimes n*ive),记得把k放在最外面就行了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 int a[2501][2501];
     6 int main()
     7 {
     8     int m,n,c,b;
     9     memset(a,0x3f,sizeof(a));
    10     scanf ("%d%d%d%d",&n,&m,&c,&b);
    11     int x,y,z;
    12     while(m--)
    13     {
    14         scanf ("%d%d%d",&x,&y,&z);
    15         a[x][y]=z;
    16         a[y][x]=z;
    17     }
    18     for(int k=1;k<=n;k++)
    19     {
    20         for(int i=1;i<=n;i++)
    21         {
    22             for(int j=1;j<=n;j++)
    23             {
    24                 a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
    25             }
    26         }
    27     }
    28     printf("%d",a[c][b]);
    29     return 0;
    30 }
    Floyd

    没有任何的参考价值,除非你要做多源最短路径(☺)

    next,SPFA算法,最短路径更快算法(☺),shortest path faster algorithm

    思想是这样的:从起点开始入队,然后每次取出一个点,消除标记,轮边松弛。

    对于松弛了的边,如果在队中就不用管。否则入队+标记。

    然后就能很naive的输出答案了!

    注意:当一个点进队超过n次就有负环。

    十分规范的模板。

     1 #include <cstdio>
     2 #include <queue>
     3 using namespace std;
     4 const int N = 1000010;
     5 int n,top;
     6 struct Edge
     7 {
     8     int u,v,len,next,num;
     9 }edge[N];
    10 struct Point
    11 {
    12     int dis=0x3f3f3f3f,e,c,num;
    13     bool vis;
    14 }point[N];
    15 
    16 bool spfa(int k)
    17 {
    18     queue<int>p;
    19     point[k].vis=1;
    20     point[k].c++;
    21     point[k].dis=0;
    22     p.push(k);
    23     int op,ed,i;
    24     while(!p.empty())
    25     {
    26         op=p.front();
    27         p.pop();
    28         point[op].vis=0;
    29         i=point[op].e;
    30         while(i)
    31         {
    32             ed=edge[i].v;
    33             if(point[ed].dis>point[op].dis+edge[i].len)
    34             {
    35                 point[ed].dis=point[op].dis+edge[i].len;
    36                 if(point[ed].vis) continue;
    37                 point[ed].vis=1;
    38                 p.push(ed);
    39                 point[ed].c++;
    40                 if(point[ed].c>n) return 0;
    41             }
    42             i=edge[i].next;
    43         }
    44     }
    45     return true;
    46 }
    47 void add(int x,int y,int z)
    48 {
    49     top++;
    50     edge[top].u=x;
    51     edge[top].v=y;
    52     edge[top].len=z;
    53     edge[top].num=top;
    54     edge[top].next=point[x].e;
    55     point[x].e=top;
    56     return;
    57 }
    58 int main()
    59 {
    60     int m,a,b;
    61     scanf ("%d%d%d%d",&n,&m,&a,&b);
    62     for(int i=1;i<=n;i++) point[i].num=i;
    63     int x,y,z;
    64     for(int i=1;i<=m;i++)
    65     {
    66         scanf ("%d%d%d",&x,&y,&z);
    67         add(x,y,z);
    68         add(y,x,z);
    69     }
    70     if(!spfa(a)) printf("-1");
    71     else printf("%d",point[b].dis);
    72     return 0;
    73 }
    SPFA spfa

    接下来是稠密图上的dijkstra算法,di jk s tra(☺)

    思想:来个优先队列,dis小的点先出。

    起点入队,然后每次取出一个未标记的点标记已读,然后轮边。

    如果终点被标记就continue,记得更新i。否则松弛一下,不管有没有成功都入队。

    今天刚打的代码,也很规范。

    (缺点:边权不能为负)

     1 #include <cstdio>
     2 #include <queue>
     3 using namespace std;
     4 const int N = 1000010;
     5 int top;
     6 struct Edge
     7 {
     8     int u,v,len,next,num;
     9 }edge[N];
    10 struct Point
    11 {
    12     int e,dis=0x3f3f3f3f,c,num;
    13     bool vis;
    14     bool operator < (const Point &a) const
    15     {
    16         return this->dis > a.dis;
    17     }
    18 }point[N];
    19 
    20 void dijkstra(int k)
    21 {
    22     priority_queue<Point>p;
    23     p.push(point[k]);
    24     point[k].vis=1;
    25     point[k].dis=0;
    26     int op,ed,i;
    27     while(!p.empty())
    28     {
    29         while((!p.empty())&&(p.top().vis)) p.pop();
    30         if(p.empty()) break;
    31         op=p.top().num;
    32         p.pop();
    33         point[op].vis=1;
    34         i=point[op].e;
    35         while(i)
    36         {
    37             ed=edge[i].v;
    38             if(point[ed].vis) {i=edge[i].next;continue;}
    39             if(point[ed].dis>point[op].dis+edge[i].len) point[ed].dis=point[op].dis+edge[i].len;
    40             p.push(point[ed]);
    41             i=edge[i].next;
    42         }
    43     }
    44     return;
    45 }
    46 
    47 
    48 void add(int x,int y,int z)
    49 {
    50     top++;
    51     edge[top].u=x;
    52     edge[top].v=y;
    53     edge[top].len=z;
    54     edge[top].num=top;
    55     edge[top].next=point[x].e;
    56     point[x].e=top;
    57     return;
    58 }
    59 int main()
    60 {
    61     int m,n,a,b;
    62     scanf ("%d%d%d%d",&n,&m,&a,&b);
    63     int x,y,z;
    64     for(int i=1;i<=n;i++) point[i].num=i;
    65     while(m--)
    66     {
    67         scanf ("%d%d%d",&x,&y,&z);
    68         add(x,y,z);
    69         add(y,x,z);
    70     }
    71     dijkstra(a);
    72     printf("%d",point[b].dis);
    73     return 0;
    74 }
    Dijkstra

    That's all,thanks for watching.

  • 相关阅读:
    python记录程序运行时间的三种方法
    LeetCode 922. 按奇偶排序数组 II 做题小结
    LeetCode 976. 三角形的最大周长 做题小结
    LeetCode 1122. 数组的相对排序 做题小结
    LeetCode1528. 重新排列字符串 做题小结
    LeetCode 738. 单调递增的数字 做题小结
    selenium——鼠标操作ActionChains:点击、滑动、拖动
    剑指 Offer 32
    剑指 Offer 32
    二叉树的应用:二叉排序树的删除
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/8579925.html
Copyright © 2020-2023  润新知