gdfzoj #768 百度地图导航(SPFA+建图)
来源:互联网 发布:java生日祝福程序代码 编辑:程序博客网 时间:2024/06/16 22:20
原题:2017计蒜之道复赛Problem D
标签:建图,SPFA
题目链接
Problem Description
百度地图上有 n 个城市,城市编号依次为 1 到 n。地图中有若干个城市群,编号依次为 1 到 m。每个城市群包含一个或多个城市;每个城市可能属于多个城市群,也可能不属于任何城市群。
地图中有两类道路。第一类道路是 城市之间的快速路,两个城市 u,v 之间增加一条距离为 c 的边;第二类道路是 城市群之间的高速路,连接两个城市群 a,b,通过这条高速路,城市群 a 里的每个城市与城市群b 里的每个城市之间两两增加一条距离为 c 的边。图中所有边均为无向边。
你需要计算从城市 s 到城市 t 的最短路。
Input
第一行输入n, m,分别表示城市总数和城市群总数。
接下来一共输入 m 行。
第 i 行首先输入一个k[i] (1≤k[i]≤n),表示第 i个城市群中的城市数为k[i]。接下来输入 k[i]个数,表示第 i 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法, ∑k[i]≤20000)
下一行输入一个整数m1 (0≤m[1]≤n),表示有 m1条第一类道路,即城市之间的快速路。
接下来 m1行,每行输入三个整数u[i] ,v[i](1≤u[i] ,v[i]≤n),c[i] (1≤c[i]≤10^6 ),分别表示快速路连接的两个城市编号和边的距离。
下一行输入一个整数 m2(0≤m2 ≤m),表示有 m2条第二类道路,即城市群之间的高速路。
接下来 m2行,每行输入三个整数 a[i] ,b[i] (1≤a[i] ,b[i]≤m),l[i] (1≤l[i]≤10^6 ),分别表示快速路连接的两个城市群编号和边的距离。
最后一行输入 s,t(1≤s,t≤n),表示起点和终点城市编号。
输入范围
对于30%的数据,n<=200,m=0
对于50%的数据,n,m<=200
对于100%的数据,2<=n<=20000,0<=m<=20000
Output
输出一个整数,表示城市 s 到城市 t 到最短路。如果不存在路径,则输出-1。
Sample Input
5 4
2 5 1
2 2 4
1 3
2 3 4
2
1 2 9
1 5 18
2
1 2 6
1 3 10
1 5
Sample Output
12
这道题大意是给出城市及城市圈,已经它们之间的距离,求最短路,我们不难想到用spfa。所以这里重点讲如何建图。
建图就是对于城市之间的边保持不变,对于城市圈,有性质“城市群 a 里的每个城市与城市群b 里的每个城市之间两两增加一条距离为 c 的边”,基于这个性质,我们可以将城市圈新建为一个点,为了避免与已有点的编号重合,我们令城市圈i的点编号为i+n。
有了这个点,我们可以将城市圈中的城市的点与城市圈所表示的点连起来,当然,路径长度为0。
注意到一个问题:这样做会导致同一城市圈中的点(假设为A,B)的距离变为0。(想一想,为什么)为了避免这种情况的出现,我们可以将一个城市圈用两个点表示,将城市圈中的城市的点与城市圈所表示的点的路径单向化。这样就可以避免上述问题。令城市圈i所表示的两个点编号分别为i+n,i+2*n(这意味着,邻接表需要开到3倍大小)。
当连接i,j两个城市圈时,我们只需连接(i+n,j+2*n),(j+n,i+2*n)两条单向边即可。
详见代码。
#include<cstdio>#include<algorithm>#include<cstring>#define maxn 100050#define add(u,v,vv) (to[++top]=head[u],head[u]=top,w[top]=v,val[top]=vv)#define For(x) for(int h=head[x],o=w[h],v=val[h];h;o=w[h=to[h]],v=val[h])using namespace std;int q[maxn],head[maxn],val[maxn],to[maxn],w[maxn],i,j,l,r,d[maxn],s,t,n,m,k,top,m1,m2,x,y,z;bool f[maxn];void spfa(){ memset(f,0,sizeof(f)); memset(d,0x7f,sizeof(d)); d[s]=0; f[s]=1; q[l=r=0]=s; while (l<=r) { int x=q[l]; For (x) { if (v+d[x]<d[o]) { d[o]=v+d[x]; if (!f[o]) { f[o]=1; q[++r]=o; } } } f[x]=0; l++; }}int main(){ scanf("%d%d",&n,&m); for (i=1;i<=m;i++) { scanf("%d",&k); for (j=1;j<=k;j++) scanf("%d",&s),add(s,i+n,0),add(i+n*2,s,0); } scanf("%d",&m1); for (i=1;i<=m1;i++) scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z); scanf("%d",&m2); for (i=1;i<=m2;i++) { scanf("%d%d%d",&x,&y,&z); add(x+n,y+2*n,z); add(y+n,x+n*2,z); } scanf("%d%d",&s,&t); spfa(); if (d[t]!=d[0]) printf("%d",d[t]);else printf("-1"); return 0;}
- gdfzoj #768 百度地图导航(SPFA+建图)
- 百度地图 API 导航
- 百度地图导航
- binbinyang---百度地图-导航
- 百度地图导航问题
- 百度地图之导航
- iOS百度地图导航
- 计蒜客 百度地图导航
- 计蒜客 百度地图导航
- 百度地图SDK导航(路径规划+实时导航)
- Android studio 百度地图开发(3)地图导航
- IOS 地图导航(其中包括苹果地图、百度地图、高德地图、谷歌地图)
- Android app调用第三方地图(百度地图,高德地图,谷歌地图)导航
- 百度地图基于web导航
- 百度地图导航没有声音
- 隐藏百度地图导航菜单栏
- 百度地图定位与导航
- 百度地图web版导航
- ORACLE中触发器实现删除一张表中数据同时删除另一表中相关数据
- FZU 2270 Two Triangles (计算几何)
- java 标记接口
- 树莓派+motion 实现 监控
- C# double[][] 的排序问题
- gdfzoj #768 百度地图导航(SPFA+建图)
- java异常处理机制深入理解
- 例4.11 访问声明的引例
- Ubuntu安装配置vsftpd
- python核心编程v2.0 第六章习题答案
- ACM_06
- 51nod1046
- 例4.12 访问声明的应用
- UVA 839 Not so Mobile