浏览器标题切换
浏览器标题切换end

寒假Day7:最短路

HDU2112-HDU Today-dijkstra

题面:

经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区500强。这时候,XHD夫妇也退居了二线,并在风景秀美的诸暨市浬浦镇陶姚村买了个房子,开始安度晚年了。
这样住了一段时间,徐总对当地的交通还是不太了解。有时很郁闷,想去一个地方又不知道应该乘什么公交车,在什么地方转车,在什么地方下车(其实徐总自己有车,却一定要与民同乐,这就是徐总的性格)。
徐总经常会问蹩脚的英文问路:“Can you help me?”。看着他那迷茫而又无助的眼神,热心的你能帮帮他吗?
请帮助他用最短的时间到达目的地(假设每一路公交车都只在起点站和终点站停,而且随时都会开)。
Input
输入数据有多组,每组的第一行是公交车的总数N(0<=N<=10000);
第二行有徐总的所在地start,他的目的地end;
接着有n行,每行有站名s,站名e,以及从s到e的时间整数t(0<t<100)(每个地名是一个长度不超过30的字符串)。
note:一组数据中地名数不会超过150个。
如果N==-1,表示输入结束。
Output
如果徐总能到达目的地,输出最短的时间;否则,输出“-1”。
View Code

样例:

Sample Input
6
xiasha westlake
xiasha station 60
xiasha ShoppingCenterofHangZhou 30
station westlake 20
ShoppingCenterofHangZhou supermarket 10
xiasha supermarket 50
supermarket westlake 10
-1

Sample Output
50


Hint:
The best route is:
xiasha->ShoppingCenterofHangZhou->supermarket->westlake

题意:问给定的起点到终点的最短时间。

思路:dijkstra模板

注意:坑比较多

  • 起点和终点可能是同一个点
  • 双向边且取最小值
  • 有map的应用,用于给定的起点和终点都是字符串,给定经过的点也是以字符串的形式存储
sum=0;
string st,en;
cin>>st>>en;
mp[st]=++sum;
mp[en]=++sum;
for(int i=1; i<=n; i++)
{
    string ss,ee;
    int t;
    cin>>ss>>ee>>t;
    if(!mp[ss])
        mp[ss]=++sum;
    if(!mp[ee])
        mp[ee]=++sum;
    if(e[mp[ss]][mp[ee]]>t||e[mp[ee]][mp[ss]]>t)
        e[mp[ss]][mp[ee]]=e[mp[ee]][mp[ss]]=t;
}

 

顺带回顾一下dijkstra

 1 void dijkstra()
 2 {
 3     for(int i=1;i<=sum;i++)
 4     {
 5         dist[i]=e[1][i];
 6         book[i]=0;
 7     }
 8     book[1]=1,dist[1]=0;
 9     int u;
10     for(int i=2;i<=sum;i++)
11     {
12         int minn=inf;
13         for(int j=1;j<=sum;j++)
14         {
15             if(book[j]==0&&minn>dist[j])
16             {
17                 u=j;
18                 minn=dist[j];
19             }
20         }
21         if(minn==inf)
22             break;
23         book[u]=1;
24         for(int j=1;j<=sum;j++)
25         {
26             if(book[j]==0&&dist[u][j]<inf)
27             {
28                 if(dist[u]+e[u][j]<dist[j])
29                     dist[j]=dist[u]+e[u][j];
30             }
31         }
32     }
33 
34 }
View Code

 

 

AC代码如下:

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #include<algorithm>
  5 #include<queue>
  6 #include<map>
  7 #include<cmath>
  8 using namespace std;
  9 #define inf 0x3f3f3f3f
 10 const int N=1e4+20;
 11 
 12 int e[N][N],dist[N];
 13 int sum;
 14 bool book[N];
 15 map<string,int>mp;
 16 
 17 void init()
 18 {
 19     for(int i=1;i<=150;i++)
 20     {
 21         for(int j=1;j<=150;j++)
 22         {
 23             if(i==j)
 24                 e[i][j]=0;
 25             else
 26                 e[i][j]=inf;
 27         }
 28     }
 29 }
 30 
 31 void dijkstra()
 32 {
 33     for(int i=1;i<=sum;i++)
 34     {
 35         dist[i]=e[1][i];
 36         book[i]=0;
 37     }
 38     book[1]=1,dist[1]=0;
 39     int u;
 40     for(int i=2;i<=sum;i++)
 41     {
 42         int minn=inf;
 43         for(int j=1;j<=sum;j++)
 44         {
 45             if(book[j]==0&&minn>dist[j])
 46             {
 47                 u=j;
 48                 minn=dist[j];
 49             }
 50         }
 51         if(minn==inf)
 52             break;
 53         book[u]=1;
 54         for(int j=1;j<=sum;j++)
 55         {
 56             if(book[j]==0)
 57             {
 58                 dist[j]=min(dist[j],dist[u]+e[u][j]);
 59             }
 60         }
 61     }
 62 
 63 }
 64 
 65 int main()
 66 {
 67     ios::sync_with_stdio(false);
 68     int n;
 69     while(cin>>n)
 70     {
 71         if(n==-1)
 72             break;
 73         mp.clear();
 74         init();
 75         sum=0;
 76         string st,en;
 77         cin>>st>>en;
 78         mp[st]=++sum;
 79         mp[en]=++sum;
 80         for(int i=1;i<=n;i++)
 81         {
 82             string ss,ee;
 83             int t;
 84             cin>>ss>>ee>>t;
 85             if(!mp[ss])
 86                 mp[ss]=++sum;
 87             if(!mp[ee])
 88                 mp[ee]=++sum;
 89             if(e[mp[ss]][mp[ee]]>t||e[mp[ee]][mp[ss]]>t)
 90                 e[mp[ss]][mp[ee]]=e[mp[ee]][mp[ss]]=t;
 91         }
 92         //cout<<"---"<<sum<<endl;
 93         dijkstra();
 94         if(st==en)
 95         {
 96             cout<<0<<endl;
 97             continue;
 98         }
 99         //int w=e[1][2];
100         int w=dist[2];
101         if(w!=inf)
102             cout<<w<<endl;
103         else
104             cout<<"-1"<<endl;
105     }
106     return 0;
107 }
View Code

 

      

 

HDU6714-最短路2-Floyd

  • 法一:一种是用dijkstra写的,但是我没看懂。。。

                     参考博客:https://blog.csdn.net/birdmanqin/article/details/100068433

                                       https://www.cnblogs.com/iat14/p/11408298.html

  • 法二:一种用floyd写的(以下思路和代码是用floyd写的)

题面:

小 A 是社团里的工具人,有一天他的朋友给了他一个 n 个点,m 条边的正权连通无向图,要他计算所有点两两之间的最短路。

作为一个工具人,小 A 熟练掌握着 floyd 算法,设 w[i][j] 为原图中 (i,j) 之间的权值最小的边的权值,若没有边则 w[i][j]=无穷大。特别地,若 i=j,则 w[i][j]=0。

Floyd 的 C++ 实现如下:

```c++
for(int k=1;k<=p;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
  w[i][j]=min(w[i][j],w[i][k]+w[k][j]);
```

当 p=n 时,该代码就是我们所熟知的 floyd,然而小 A 为了让代码跑的更快点,所以想减少 p 的值。

令 Di,j 为最小的非负整数 x,满足当 p=x 时,点 i 与点 j 之间的最短路被正确计算了。

现在你需要求 ∑ni=1∑nj=1Di,j,虽然答案不会很大,但为了显得本题像个计数题,你还是需要将答案对 998244353 取模后输出。
Input
第一行一个正整数 T(T≤30) 表示数据组数

对于每组数据:

第一行两个正整数 n,m(1≤n≤1000,m≤2000),表示点数和边数。

保证最多只有 5 组数据满足 max(n,m)>200

接下来 m 行,每行三个正整数 u,v,w 描述一条边权为 w 的边 (u,v),其中 1≤w≤109
Output
输出 T 行,第 i 行一个非负整数表示第 i 组数据的答案

Sample Input
1
4 4
1 2 1
2 3 1
3 4 1
4 1 1

Sample Output
6
View Code

 

题意:求所有顶点N中任意两点最短路中松弛点中最小值的和

注意:

  • 用floyd很容易超时,这个地方处理很好。但是得放在第二层循环下,放在第三层会超时;
if(e[i][k]>inff)
    continue;
  • 虽然每条边给的范围是109,但是由于floyd中会进行边的松弛,也就是会进行相加,所以需要开数组为ll;
  • 因为大部分数据开的为ll,所以在对于边的处理应该初始化为ll型的无穷大,也就是0x3f3f3f3f3f3f3f3f(8个3f),约19位;
  • 在处理数据的时候,第三层for循环到 j<i 即可,之后的结果*2,因为是双向边,所以后面的和前面一样也就无需重复处理了。

 

代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<map>
 8 #include<cmath>
 9 using namespace std;
10 #define inf 0x3f3f3f3f
11 #define inff 0x3f3f3f3f3f3f3f3f
12 const int N=1010;
13 #define mod 998244353
14 typedef long long ll;
15 
16 ll e[N][N],dist[N],a[N][N];
17 int n,m;
18 bool book[N];
19 map<string,int>mp;
20 
21 void init()
22 {
23     for(int i=1;i<=n;i++)
24     {
25         for(int j=1;j<=n;j++)
26         {
27             if(i==j)
28                 e[i][j]=0;
29             else
30                 e[i][j]=inff;
31         }
32     }
33 }
34 
35 int main()
36 {
37     ios::sync_with_stdio(false);
38     int t;
39     cin>>t;
40     while(t--)
41     {
42         cin>>n>>m;
43         memset(a,0,sizeof(a));
44         init();
45         for(int i=1;i<=m;i++)
46         {
47             ll u,v,w;
48             cin>>u>>v>>w;
49             e[u][v]=e[v][u]=min(e[u][v],w);
50         }
51         ll ans=0;
52         for(int k=1;k<=n;k++)
53         {
54             for(int i=1;i<=n;i++)
55             {
56                 if(e[i][k]>inff)
57                         continue;
58                 for(int j=1;j<i;j++)
59                 {
60                     if(e[i][j]>e[i][k]+e[k][j])
61                     {
62                         ans+=k;
63                         ans-=a[i][j];
64                         a[i][j]=a[j][i]=k;
65                         e[i][j]=e[j][i]=e[i][k]+e[k][j];
66                     }
67                 }
68             }
69         }
70         //i:4 j:2 k:1
71         //i:3 j:1 k:2
72         ll w=ans*2%mod;
73         cout<<w<<endl;
74     }
75     return 0;
76 }

 

 

 

 

 

 

 


 

小知识点回顾:

  • 0x3f3f3f3f3f3f3f3f 代表针对longlong表示的无穷大,约19位
  • dijkstra:时间复杂度O(n2),一般求单源最短路

                         针对无负权边的图,有向无向都可以

                         存储结构上比较占空间,因为用的是邻接矩阵。

  • floyd:适用于N比较小的情况。

                      注意模板上k是写在最外层循环。

for(int k=1;k<=n;k++)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            e[i][j]=min(e[i][j],e[i][k]+e[k][j]);
        }
    }
}
  • SPFA:不能处理负权回路;
  • 最短路在处理初始边的时候记得判断是否是双向边,是否需要取最小值;
  • 问起点到终点距离问题的时候,有时需要考虑一下起点是不是就是终点;
  • 记得对边进行初始化

 


 

 TO DO LIST

  • w 50+
  • 复习了最短路floyd/dijkstra

 


 

 

 待解决问题:

  • 为什么floyd的含k循环写在最外层? --> 枚举的松弛点
  • HDU6714 代码理解的不是很透彻,不确定自己理解的是否正确,需要推理出结果。???
posted @ 2020-01-20 23:29  抓水母的派大星  阅读(161)  评论(0编辑  收藏  举报