• #专题练习# 最短路练习


    最短路练习

    0. Til the Cows Come Home  POJ - 2387  

    完美的模板题

     1 //#include<Windows.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<queue>
     7 using namespace std;
     8 const int MAX_V = 10005;
     9 const int MAX_E = 20010;
    10 const int inf = 0x3f3f3f3f;
    11 
    12 struct ENode
    13 {
    14     int to;
    15     int Next;
    16     int w;
    17 };
    18 ENode Edegs[MAX_E];
    19 int Head[MAX_V];
    20 int Dis[MAX_V];
    21 int tnt;
    22 void Add_ENode(int u, int v, int w)
    23 {
    24     ++tnt;
    25     Edegs[tnt].to = v;
    26     Edegs[tnt].w = w;
    27     Edegs[tnt].Next = Head[u];
    28     Head[u] = tnt;
    29     ++tnt;
    30     Edegs[tnt].to = u;
    31     Edegs[tnt].w = w;
    32     Edegs[tnt].Next = Head[v];
    33     Head[v] = tnt;
    34 }
    35 struct cmpx
    36 {
    37     bool operator () (int &a, int &b) const
    38     {
    39         return Dis[a] - Dis[b] > 0;
    40     }
    41 };
    42 
    43 void Dijkstra(int x)
    44 {
    45     priority_queue<int, vector<int>, cmpx> q;
    46     memset(Dis, inf, sizeof(Dis));
    47     Dis[x] = 0;
    48     q.push(x);
    49     while (!q.empty())
    50     {
    51         int u = q.top();
    52         q.pop();
    53         for (int k = Head[u]; k != -1; k= Edegs[k].Next)
    54         {
    55             int v = Edegs[k].to;
    56             if (Dis[v] > Dis[u] + Edegs[k].w)
    57             {
    58                 Dis[v] = Dis[u] + Edegs[k].w;
    59                 q.push(v);
    60             }
    61         }
    62     }
    63 }
    64 
    65 int main()
    66 {
    67     int t, n;
    68     cin >> t >> n;
    69     tnt = -1;
    70     int a, b, w;
    71     memset(Head, -1, sizeof(Head));
    72     for (int i = 0; i < t; i++)
    73     {
    74         cin >> a >> b >> w;
    75         Add_ENode(a, b, w);
    76     }
    77     Dijkstra(1);
    78     cout << Dis[n] << endl;
    79 //    system("pause");
    80     return 0;
    81 }
    View Code

    1. Frogger POJ - 2253  

    青蛙和石头。在池塘里有2只青蛙和n块石头,石头之间有一定距离,现在一只(腿短的)青蛙想要去找另一只青蛙yuehui;给出n块石头的坐标,1号为男主青蛙所在的石头,二号为目标石头。他想尽可能的省力,每次都跳的尽量短。问它在所有可行路径中单次跳跃需要的最长距离的最小值是多少?

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<queue>
     6 #include<cmath>
     7 using namespace std;
     8 const int MAX_V= 210;
     9 const double inf= 99999999999999999.0;
    10 typedef pair<double, double> _pair;
    11 _pair rock[MAX_V];
    12 double get_dis(_pair a, _pair b)
    13 {
    14     return sqrt(((a.first- b.first)* (a.first- b.first) )+ ((a.second- b.second)* (a.second- b.second) ) );
    15 }
    16 double Dis[MAX_V];
    17 struct cmpx
    18 {
    19     bool operator() (int &a, int &b) const
    20     {
    21         return Dis[a]- Dis[b]> 0; 
    22     }
    23 };
    24 int Front[MAX_V];
    25 void Dijkstra(int n)
    26 {
    27     priority_queue<int, vector<int>, cmpx> q;
    28     fill(Dis, Dis+ n+ 1, inf);
    29     //for(int i= 1; i<= n; i ++) printf("%f
    ", Dis[2]);
    30     Dis[1]= 0;
    31     Front[1]= -1;
    32     q.push(1);
    33     while (! q.empty() )
    34     {
    35         int u= q.top();
    36         q.pop();
    37         for (int i= 2; i<= n; i ++)
    38         {
    39             if (i== u) continue;
    40             double detmp= get_dis(rock[u], rock[i]);
    41             //printf("%f---%f---%f
    ", Dis[u], detmp, Dis[i]);
    42             if (Dis[i]> Dis[u]&& Dis[i]> detmp)
    43             {
    44                 Dis[i]= max(Dis[u], detmp);
    45                 Front[i]= u;
    46                 q.push(i);
    47             }
    48             //printf("%f
    ", Dis[i]);
    49         }
    50     }
    51 }
    52 int main()
    53 {
    54     int n;
    55     int t= 0;
    56     while (cin >> n)
    57     {
    58         ++ t;
    59         if (n== 0) break;
    60         for (int i= 1; i<= n; i ++)
    61         {
    62             cin >> rock[i].first >> rock[i].second;
    63         }
    64         //for(int i= 2; i<= n; i ++) printf("%f
    ", get_dis(rock[1], rock[i]));
    65         Dijkstra(n);
    66         printf("Scenario #%d
    ",t);
    67         printf("Frog Distance = %.3f
    
    ", Dis[2]);
    68         double ans= -1.0;
    69         /*for (int c= n; c!= 1; c= Front[c])
    70         {
    71             double cnp= get_dis(rock[c], rock[Front[c]]);
    72             ans= max(ans, cnp);
    73         }
    74         printf("Frog Distance = %.3f
    
    ", ans);*/
    75     }
    76     return 0;
    77 }
    View Code

    2. Heavy Transportation POJ - 1797  

    城市中有N个路口,M个街道,每条街道都有最大承重限制;现在我们想要驾车从1号路口到N号路口,那么运输车所允许的最大重量是多少?

    (不知道为什么老是PE,懒得改了)

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<queue>
     6 using namespace std;
     7 const int maxv= 100010;
     8 const int maxe= 2100010;
     9 const int inf= 0x3f3f3f3f;
    10 
    11 struct ENode
    12 {
    13     int to;
    14     int w;
    15     int Next;
    16 };
    17 ENode edegs[maxe];
    18 int Head[maxv], tnt;
    19 void init()
    20 {
    21     memset(Head, -1, sizeof(Head));
    22     tnt= -1;
    23 }
    24 void Add_ENode(int a, int b, int w)
    25 {
    26     ++ tnt;
    27     edegs[tnt].to= b;
    28     edegs[tnt].w= w;
    29     edegs[tnt].Next= Head[a];
    30     Head[a]= tnt;
    31     ++ tnt;
    32     edegs[tnt].to= a;
    33     edegs[tnt].w= w;
    34     edegs[tnt].Next= Head[b];
    35     Head[b]= tnt;
    36 }
    37 
    38 int dis[maxv];
    39 struct cmpx
    40 {
    41     bool operator() (int &a, int &b) const
    42     {
    43         return dis[a]- dis[b]< 0;
    44     }
    45 };
    46 void Dijkstra(int x)
    47 {
    48     priority_queue<int, vector<int>, cmpx> q;
    49     memset(dis, 0, sizeof(dis));
    50     dis[x]= inf;
    51     q.push(x);
    52 
    53     while (! q.empty())
    54     {
    55         int u= q.top();
    56         q.pop();
    57         for (int k= Head[u]; k!= -1; k= edegs[k].Next)
    58         {
    59             int v= edegs[k].to;
    60             if (dis[v]< min(dis[u], edegs[k].w))
    61             {
    62                 dis[v]= min(dis[u], edegs[k].w);
    63                 q.push(v);
    64             }
    65         }
    66     }
    67 }
    68 
    69 int main()
    70 {
    71     int t, Case= 0;
    72     int n, m;
    73     scanf("%d", &t);
    74     while (t --)
    75     {
    76         ++ Case;
    77         scanf("%d %d", &n, &m);
    78         init();
    79         int a, b, w;
    80         for (int i= 0; i< m; i ++)
    81         {
    82             scanf("%d %d %d", &a, &b, &w);
    83             Add_ENode(a, b, w);
    84         }
    85         Dijkstra(1);
    86         printf("Scenario #%d:
    %d
    ", Case, dis[n]);
    87     }
    88     return 0;
    89 }
    View Code

    3. Travel (The 2019 ACM-ICPC China Shannxi Provincial Programming Contest M)  /**计蒜客复现赛:点这里*/

    星系中有n 个星球,编号从1 到N。星球之间有M个隧道相连,每个隧道都有一个长度。你有一个航天器,航天器有两个属性:传输距离d 和传输次数e 。航天器只能通过短于或等于其传输距离的通道;如果传输次数耗尽,则无法再使用航天器。航天器具有等级,lv0的航天器d 和e 都等于0,你可以给你的航天器升级,每次升级都会消耗c 点花费,给你的航天器提升dx和 ex点属性。现在,告诉你n,m,m条通道的信息,还有给你的航天器升级时的c,dx,ex。

    Q: 你能求出从1 到N 的最小花费吗?

    A: 把原本记录到达此点最短距离的Dis[] 变成 记录到达此点所需要飞行器最低等级的Dis_Level[],这样剩下的就是普通的Dijkstra了。

     1 #include<algorithm>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<queue>
     5 using namespace std;
     6 const int MAX_V= 100010;
     7 const int MAX_E= 400010;
     8 const int inf= 0x3f3f3f3f;
     9 
    10 struct ENode
    11 {
    12     int to;
    13     int w;
    14     int Next;
    15 };
    16 ENode edegs[MAX_E];
    17 int Head[MAX_V], tnt;
    18 void Add_ENode(int a, int b, int w)
    19 {
    20     edegs[++ tnt].to= b;
    21     edegs[tnt].w= w;
    22     edegs[tnt].Next= Head[a];
    23     Head[a]= tnt;
    24     edegs[++ tnt].to= a;
    25     edegs[tnt].w= w;
    26     edegs[tnt].Next= Head[b];
    27     Head[b]= tnt;
    28 }
    29 
    30 int Dis_Level[MAX_V];  //到每个点,所需要的飞船最小等级;
    31 int deep[MAX_V];  //每个点bfs 的深度;
    32 struct cmpx
    33 {
    34     bool operator() (int &a, int &b) const
    35     {
    36         return Dis_Level[a]- Dis_Level[b]> 0;
    37     }
    38 };
    39 void Dijkstra(int x, int _dis, int _cost)
    40 {
    41     /*x为起点, _dis是每次升级提升的传送距离, _cost是升级提升的传送次数;*/
    42     memset(Dis_Level, inf, sizeof(Dis_Level));
    43     memset(deep, inf, sizeof(deep));
    44     priority_queue<int, vector<int>, cmpx> q;
    45     Dis_Level[x]= 0; //起点的飞行器等级为0;
    46     deep[x]= 0;  //起点深度为0;
    47     q.push(x);
    48     while (! q.empty())
    49     {
    50         int u= q.top();
    51         q.pop();
    52         for (int k= Head[u]; k!= -1; k= edegs[k].Next)
    53         {
    54             int v= edegs[k].to;
    55             int lev_tmp= Dis_Level[u];
    56             while (lev_tmp* _dis< edegs[k].w|| lev_tmp* _cost< deep[u]+ 1)
    57             {
    58                 /*若当前的飞行器等级不能穿越此隧道,或传送次数已用完,则升级飞行器一次;*/
    59                 lev_tmp ++;
    60             }
    61             if (lev_tmp< Dis_Level[v])
    62             {
    63                 /*如果此时的飞行器等级小与之前到达点v 的飞行器等级,则更新Dis_Level[v]*/
    64                 Dis_Level[v]= lev_tmp;
    65                 deep[v]= deep[u]+ 1; //深度也要 +1;
    66                 q.push(v); //加入队列;
    67             }
    68         }
    69     }
    70 }
    71 void into()
    72 {
    73     memset(Head, -1, sizeof(Head));
    74     tnt= -1;
    75 }
    76 
    77 int main()
    78 {
    79     int n, m;
    80     int c, d, e;
    81     int a, b ,w;
    82     while (~ scanf("%d %d", &n, &m))
    83     {
    84         scanf("%d %d %d", &c, &d, &e);
    85         into();
    86         for (int i= 0;i< m;i ++)
    87         {
    88             scanf("%d %d %d", &a, &b, &w);
    89             Add_ENode(a, b, w);
    90         }
    91         Dijkstra(1, d, e);
    92         if (Dis_Level[n]== inf) printf("-1
    ");
    93         else printf("%lld
    ", (long long)Dis_Level[n]* c);
    94     }
    95     return 0;
    96 }
    View Code

    4.Marriage Match IV (HDU 3416)

    Starvae在A市,女孩在B市。每次starvae都可以到达B市并与他喜欢的女孩一起xoxo。但是他面前有两个问题,一是starvae必须在最短的时间内到达B,所以说他必须选择最短的路径;二是每条道路只能走一次,但每座城市他可以经过多次。那么,请你告诉他:从A-->B的(完全不同的)最短路径一共有几条?

    Ps:最短路径+最大流。先用Dijkstra求出A到B的最短路径并处理dis[]数组,然后依照条件(dis[v]== dis[u]+ edegs[k].w)找出所有在最短路径上的边,并建一个图2。随后就是Dinic跑最大流出结果,代码如下。

      1 #include<algorithm>
      2 #include<iostream>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<queue>
      6 using namespace std;
      7 const int maxv= 1010;
      8 const int maxe= 400010;
      9 const int inf= 0x3f3f3f3f;
     10 
     11 struct ENode
     12 {
     13     int to;
     14     int w;
     15     int Next;
     16 };
     17 ENode edegs[maxe];
     18 int Head[maxv], tnt;
     19 void init()
     20 {
     21     memset(Head, -1, sizeof(Head));
     22     tnt= -1;
     23 }
     24 void Add_ENode(int a, int b, int w)
     25 {
     26     ++ tnt;
     27     edegs[tnt].to= b;
     28     edegs[tnt].w= w;
     29     edegs[tnt].Next= Head[a];
     30     Head[a]= tnt;
     31 }
     32 
     33 int dis[maxv];
     34 struct cmpx
     35 {
     36     bool operator() (int &a, int &b) const
     37     {
     38         return dis[a]- dis[b]> 0;
     39     }
     40 };
     41 void Dijkstra(int x)
     42 {
     43     priority_queue<int, vector<int>, cmpx> q;
     44     memset(dis, inf, sizeof(dis));
     45     dis[x]= 0;
     46     q.push(x);
     47 
     48     while (! q.empty())
     49     {
     50         int u= q.top();
     51         q.pop();
     52 
     53         for (int k= Head[u]; k!= -1; k= edegs[k].Next)
     54         {
     55             int v=  edegs[k].to;
     56             if (dis[v]> dis[u]+ edegs[k].w )
     57             {
     58                 dis[v]= dis[u]+ edegs[k].w;
     59                 q.push(v);
     60             }
     61         }
     62     }
     63 }
     64 
     65 /*建新图,跑最大流*/
     66 ENode edegs1[maxe];
     67 int Head1[maxv], tnt1;
     68 void init1()
     69 {
     70     memset(Head1, -1, sizeof(Head1));
     71     tnt1= -1;
     72 }
     73 void Add_ENode1(int a, int b, int w)
     74 {
     75     ++ tnt1;
     76     edegs1[tnt1].to= b;
     77     edegs1[tnt1].w= w;
     78     edegs1[tnt1].Next= Head1[a];
     79     Head1[a]= tnt1;
     80     ++ tnt1;
     81     edegs1[tnt1].to= a;
     82     edegs1[tnt1].w= 0;
     83     edegs1[tnt1].Next= Head1[b];
     84     Head1[b]= tnt1;
     85 }
     86 void Dijk2(int n)
     87 {
     88     init1();
     89     for (int u= 1; u<= n; u ++)
     90     {
     91         for (int k= Head[u]; k!= -1; k= edegs[k].Next)
     92         {
     93             int v=  edegs[k].to;
     94             if (dis[v]== dis[u]+ edegs[k].w )
     95             {
     96                 Add_ENode1(u, v, 1);
     97             }
     98         }
     99     }
    100 }
    101 int level[maxv];
    102 bool bfs_level (int s, int t)
    103 {
    104     memset(level, -1, sizeof(level)); //所有点的等级初始化为-1;
    105     level[s]= 1; //源点的等级为1;
    106     int que[maxv];  //队列que:按序保存已搜索到的点;
    107     int iq= 0;
    108     que[iq ++]= s; //先将源点s 加入队列;
    109     for (int i= 0; i< iq; i ++)
    110     {
    111         int u= que[i];  //取出队首元素;
    112         if (u== t)
    113         {
    114             /*找到汇点t,返回*/
    115             return true;
    116         }
    117         for (int k= Head1[u]; k!= -1; k= edegs1[k].Next)
    118         {
    119             /*遍历,查找到之前未找到的、可抵达的点便加入队列*/
    120             int v= edegs1[k].to;
    121             if (-1== level[v]&& edegs1[k].w)
    122             {
    123                 level[v]= level[u]+ 1; //深度 +1;
    124                 que[iq ++]= v;
    125             }
    126         }
    127     }
    128     return false;
    129 }
    130 int dfs(int now, int c_max, int t)
    131 {
    132     /**DFS 实现多路增广*/
    133     /*now:起点;c_max:从源点s到节点now的最大流量;t:汇点、dfs结束的终点*/
    134     if (now== t) return c_max; //当now== t时,c_max便是要求的最大流;
    135     int ret= 0, f;
    136     for (int k= Head1[now]; k!= -1; k= edegs1[k].Next)
    137     {
    138         if (edegs1[k].w&& level[edegs1[k] .to]== level[now]+ 1)
    139         {
    140             /**/
    141             f= dfs(edegs1[k].to, min(c_max- ret, edegs1[k].w), t);
    142             edegs1[k].w-= f;
    143             edegs1[k^1].w+= f;
    144             ret+= f;
    145             if(ret== c_max) return ret;
    146         }
    147     }
    148     return ret;
    149 }
    150 int dinic(int s, int t)
    151 {
    152     int ans= 0;
    153     while(bfs_level(s, t))
    154     {
    155         ans+= dfs(s, inf, t);
    156     }
    157     return ans;
    158 }
    159 
    160 int main()
    161 {
    162     int t;
    163     int n, m;
    164     scanf("%d", &t);
    165     while (t --)
    166     {
    167         scanf("%d %d", &n, &m);
    168         init();
    169         int a, b, w;
    170         for (int i= 0; i< m; i ++)
    171         {
    172             scanf("%d %d %d", &a, &b, &w);
    173             Add_ENode(a, b, w);
    174         }
    175         int start, endd;
    176         scanf("%d %d", &start, &endd);
    177         Dijkstra(start);
    178         Dijk2(n);
    179         int ans= dinic(start, endd);
    180         printf("%d
    ", ans);
    181     }
    182     return 0;
    183 }
    View Code

    end;

  • 相关阅读:
    How to Use .Net Remoting Using C#
    How to: Build a Client Application
    C# 禁用鼠标中间键
    秒杀系统:设计方案与实现思路
    JDBC连接数据库
    Java调用webService示例
    spring MVC
    rust贪吃蛇
    初识智遥工作流软件——表单开发篇2
    初识智遥工作流软件——表单开发篇1
  • 原文地址:https://www.cnblogs.com/Amaris-diana/p/10778340.html
Copyright © 2020-2023  润新知