(最短路)2017 计蒜之道 复赛 D. 百度地图导航

百度地图上有 nn 个城市,城市编号依次为 11 到 nn。地图中有若干个城市群,编号依次为 11 到 mm。每个城市群包含一个或多个城市;每个城市可能属于多个城市群,也可能不属于任何城市群。

地图中有两类道路。第一类道路是 城市之间的快速路,两个城市 u,vu,v 之间增加一条距离为 cc 的边;第二类道路是 城市群之间的高速路,连接两个城市群 a,ba,b,通过这条高速路,城市群 aa 里的每个城市与城市群 bb 里的每个城市之间两两增加一条距离为 cc 的边。图中所有边均为无向边。

你需要计算从城市 ss 到城市 tt 的最短路。

输入格式

第一行输入 n(1 \le n \le 20000),n(1≤n≤20000), m(0 \le m \le 20000)m(0≤m≤20000),分别表示城市总数和城市群总数。

接下来一共输入 mm 行。

第 ii 行首先输入一个 k_i(1 \le k_i \le n)k?i??(1≤k?i??≤n),表示第 ii 个城市群中的城市数为 k_ik?i??。接下来输入 k_ik?i?? 个数,表示第 ii 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法,\sum_{i=1}^{m}k_i \le 20000∑?i=1?m??k?i??≤20000)。

下一行输入一个整数 m_1(0 \le m_1 \le 20000)m?1??(0≤m?1??≤20000),表示有 m_1m?1?? 条第一类道路,即 城市之间的快速路。

接下来 m_1m?1?? 行,每行输入三个整数 u_i,v_i(1 \le u_i, v_i \le n),c_i(1 \le c_i \le 10^6)u?i??,v?i??(1≤u?i??,v?i??≤n),c?i??(1≤c?i??≤10?6??),分别表示快速路连接的两个城市编号和边的距离。

下一行输入一个整数 m_2(0 \le m_2 \le 20000)m?2??(0≤m?2??≤20000),表示有 m_2m?2?? 条第二类道路,即 城市群之间的高速路。

接下来 m_2m?2?? 行,每行输入三个整数 a_i,b_i(1 \le a_i, b_i \le m),l_i(1 \le l_i \le 10^6)a?i??,b?i??(1≤a?i??,b?i??≤m),l?i??(1≤l?i??≤10?6??),分别表示快速路连接的两个城市群编号和边的距离。

最后一行输入 s, t(1 \le s, t \le n)s,t(1≤s,t≤n),表示起点和终点城市编号。

输出格式

输出一个整数,表示城市 ss 到城市 tt 到最短路。如果不存在路径,则输出-1

样例说明

1 -> 2 - > 5或者1 -> 4 -> 5是最短的路径,总长度为 1212。

样例输入

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

样例输出

12

比起普通的最短路问题多了一个“城市群”的概念,本题的关键也就是在于处理城市群这一情况。暴力的将两两城市群中城市分别连边会造成MLE(感觉也会TLE)。实际上可以通过拆点的方法将一个城市群转化为2个点。一个点作为城市群的“入口”连向城市群中所有的城市,一个点作为城市群的“出口”由城市群中所有城市连向。这两类边权值为0,城市群之间的距离通过一个城市的出口连另一个城市的入口表示。之后直接运行一遍dijkstra即可。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <vector>
 12 #include <stack>
 13 #define mp make_pair
 14 //#define P make_pair
 15 #define MIN(a,b) (a>b?b:a)
 16 //#define MAX(a,b) (a>b?a:b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int MAX=6e4+5;
 20 const int MAX_V=6e4+5;
 21 const ll INF=2e11+5;
 22 //const double M=4e18;
 23 using namespace std;
 24 //const int MOD=1e9+7;
 25 typedef pair<ll,int> pii;
 26 const double eps=0.000000001;
 27 #define rank rankk
 28 struct edge
 29 {
 30     int from,to,dis;
 31     edge(int u,int v,int d):from(u),to(v),dis(d){}
 32 };
 33 struct HeapNode
 34 {
 35     ll d;
 36     int u;
 37     bool operator <(const HeapNode &rhs)const
 38     {
 39         return d>rhs.d;
 40     }
 41 };
 42 struct Dijkstra
 43 {
 44     int n,m;
 45     vector<edge> edges;
 46     vector<int>G[MAX];
 47     bool done[MAX];
 48     ll d[MAX];
 49     int p[MAX];
 50     void init(int n)
 51     {
 52         this->n=n;
 53         for(int i=1;i<=n;i++)
 54             G[i].clear();
 55         edges.clear();
 56     }
 57     void Addedge(int from,int to,int dist)
 58     {
 59         edges.push_back(edge(from,to,dist));
 60         m=edges.size();
 61         G[from].push_back(m-1);
 62     }
 63     void dijkstra(int s)
 64     {
 65         priority_queue<HeapNode>Q;
 66         for(int i=1;i<=n;i++)
 67             d[i]=INF;
 68         d[s]=0;
 69         memset(done,false,sizeof(done));
 70         Q.push((HeapNode){0,s});
 71         while(!Q.empty())
 72         {
 73             HeapNode x=Q.top();Q.pop();
 74             int u=x.u;
 75             if(done[u])
 76                 continue;
 77             done[u]=true;
 78             for(int i=0;i<G[u].size();i++)
 79             {
 80                 edge &e=edges[G[u][i]];
 81                 if(d[e.to]>d[u]+e.dis)
 82                 {
 83                     d[e.to]=d[u]+e.dis;
 84                     p[e.to]=G[u][i];
 85                     Q.push((HeapNode){d[e.to],e.to});
 86                 }
 87             }
 88         }
 89     }
 90 };
 91 int n,m;
 92 int main()
 93 {
 94     scanf("%d%d",&n,&m);
 95     Dijkstra o;
 96     o.n=n+2*m;o.m=0;
 97     for(int i=1;i<=m;i++)
 98     {
 99         int num;
100         scanf("%d",&num);
101         for(int j=1;j<=num;j++)
102         {
103             int to;
104             scanf("%d",&to);
105             o.Addedge(n+i,to,0);
106             o.Addedge(to,n+i+m,0);
107         }
108     }
109     int m1;
110     scanf("%d",&m1);
111     for(int i=1;i<=m1;i++)
112     {
113         int u,v,t;
114         scanf("%d%d%d",&u,&v,&t);
115         o.Addedge(u,v,t);
116         o.Addedge(v,u,t);
117     }
118     int m2;
119     scanf("%d",&m2);
120     for(int i=1;i<=m2;i++)
121     {
122         int u,v,t;
123         scanf("%d%d%d",&u,&v,&t);
124         o.Addedge(n+u+m,n+v,t);
125         o.Addedge(n+v+m,n+u,t);
126     }
127     int s,t;
128     scanf("%d%d",&s,&t);
129     o.dijkstra(s);
130     printf("%lld\n",o.d[t]==INF?-1LL:o.d[t]);
131     return 0;
132 }
时间: 2024-12-20 04:43:15

(最短路)2017 计蒜之道 复赛 D. 百度地图导航的相关文章

2016计蒜之道复赛A 百度地图的实时路况

百度地图的实时路况功能相当强大,能方便出行的人们避开拥堵路段.一个地区的交通便捷程度就决定了该地区的拥堵情况.假设一个地区有 nnn 个观测点,编号从 111 到 nnn.定义 d(u,v,w)d(u,v,w)d(u,v,w) 为从 uuu 号点出发,严格不经过 vvv 号点,最终到达 www 号点的最短路径长度,如果不存在这样的路径,d(u,v,w)d(u,v,w)d(u,v,w) 的值为 −1-1−1. 那么这个地区的交通便捷程度 PPP 为: P=∑1≤x,y,z≤n,x≠y,y≠zd(x

2017 计蒜之道 复赛 Windows画图+百度地图导航

因为没有休息好, 打着很异常难受的一场比赛,坚持了一个半小时就撤了. Windows画图:签到题,没什么说的. #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<iostream> #include<queue> #include<map> #include<

2017计蒜之道复赛 百度地图导航

分析:这道题本质就是很简单的最短路问题,但是如果连边用O(n^2)的暴力会直接TLE掉,连一条边的复杂度是减少不了了,那么能不能减少连边的数量呢? 我们可以设置一个中间点p,假设a中的所有点要到b中去,则从a向p连一条有向边,p向b连一条有向边,可是这样权值不好办啊,那么我们把每个城市圈当作一个中心点,这样从a连向a',a'连向b',b'连向b,除了中间这条边以外的边权值都是0,但是我也有可能从b走向a啊,那么a到a'的两条边的边权都是0,这样会陷入死循环啊? 解决方法很简单,我们把每个中心点拆

(状压dp)2017 计蒜之道 复赛 F. 腾讯消消乐

腾讯推出了一款益智类游戏--消消乐.游戏一开始,给定一个长度为 nn 的序列,其中第 ii 个数为 A_iA?i??. 游戏的目标是把这些数全都删去,每次删除的操作为:选取一段连续的区间,不妨记为 [L,R][L,R],如果这一段区间内所有数的最大公约数 \geq k≥k(kk 值在游戏的一开始会给定),那么这一段区间就能被直接删去. 注意:一次删除以后,剩下的数会合并成为一个连续区间. 定义 f(i)f(i) 为进行 ii 次操作将整个序列删完的方案数. 你需要实现一个程序,计算 \sum_{

2017 计蒜之道 初赛 第一场 B.阿里天池的新任务

2017 计蒜之道 初赛 第一场 B.阿里天池的新任务 1 /* QYP kuai wo dai ma*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<iomanip> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cstdio> 8 #include<queue> 9 #include<ctime

2017计蒜之道 初赛 第二场 百度的科学计算器(简单)

/** 题目:2017计蒜之道 初赛 第二场 百度的科学计算器(简单) 链接:https://nanti.jisuanke.com/t/15504 题意:给一个合法的表达式,包含加号+.减号-.括号().数字常量,表达式中没有空格. 输入数据保证数字常量以及计算过程中数值绝对值均不超过 10^12??,对于浮点型数值常量,保证小数点后不超过 666 位. 思路:暴力模拟:python有函数可以直接调用. 坑点:如果表达式中出现过浮点数,那么输出结果保留6位小数, 否则输出整数,不出现小数. */

2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于 10^5105 的字符串.现在魔法师想要通过一系列魔法使得这两个字符串相同.每种魔法形如 (u,\ v),\ u,\ v \le 10^5(u, v), u, v≤105,可以将一个字符 uu改成一个字符 vv,并且可以使用无限次.出于种种原因,魔法师会强行指定这两个串能否进行修改. 若失败输出 -

贝壳找房魔法师顾问 2018 计蒜之道 复赛

https://nanti.jisuanke.com/t/A1725 V&V 无向图 强连通图 每个子图,n个点,选择n-1条,使互相连接 因为目标点x->点y,可以改为点y->点x V&C 弱连通图(将有向图的所有的有向边替换为无向边,所得到的图称为原图的基图.如果一个有向图的基图是连通图,则有向图是弱连通图.) 1.一个弱连通子图,它里面的点与该弱连通子图外的点与没有关系,可以单独处理 2.弱连通子图里,一个点,必有另外点与之相邻,包括入和出 3.若弱连通子图里有环,则无论

计蒜之道复赛 B D F

B题是一个简单的模拟 求一下两个点中间在上deta的整数点 然后更新一下每个点的最后一次经过就好了 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(x) cerr<<#x<<"=="<<(x)<<endl 4 using namespace std; 5 6 const int maxn=300+10; 7 8