https://nanti.jisuanke.com/t/A1244
百度地图上有 nnn 个城市,城市编号依次为 111 到 nnn。地图中有若干个城市群,编号依次为 111 到 mmm。每个城市群包含一个或多个城市;每个城市可能属于多个城市群,也可能不属于任何城市群。
地图中有两类道路。第一类道路是 城市之间的快速路,两个城市 u,vu,vu,v 之间增加一条距离为 ccc 的边;第二类道路是 城市群之间的高速路,连接两个城市群 a,ba,ba,b,通过这条高速路,城市群 aaa 里的每个城市与城市群 bbb 里的每个城市之间两两增加一条距离为 ccc 的边。图中所有边均为无向边。
你需要计算从城市 sss 到城市 ttt 的最短路。
输入格式
第一行输入 n(1≤n≤20000),n(1 \le n \le 20000),n(1≤n≤20000), m(0≤m≤20000)m(0 \le m \le 20000)m(0≤m≤20000),分别表示城市总数和城市群总数。
接下来一共输入 mmm 行。
第 iii 行首先输入一个 ki(1≤ki≤n)k_i(1 \le k_i \le n)ki(1≤ki≤n),表示第 iii 个城市群中的城市数为 kik_iki。接下来输入 kik_iki 个数,表示第 iii 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法,∑i=1mki≤20000\sum_{i=1}^{m}k_i \le 20000∑i=1mki≤20000)。
下一行输入一个整数 m1(0≤m1≤20000)m_1(0 \le m_1 \le 20000)m1(0≤m1≤20000),表示有 m1m_1m1 条第一类道路,即 城市之间的快速路。
接下来 m1m_1m1 行,每行输入三个整数 ui,vi(1≤ui,vi≤n),ci(1≤ci≤106)u_i,v_i(1 \le u_i, v_i \le n),c_i(1 \le c_i \le 10^6)ui,vi(1≤ui,vi≤n),ci(1≤ci≤106),分别表示快速路连接的两个城市编号和边的距离。
下一行输入一个整数 m2(0≤m2≤20000)m_2(0 \le m_2 \le 20000)m2(0≤m2≤20000),表示有 m2m_2m2 条第二类道路,即 城市群之间的高速路。
接下来 m2m_2m2 行,每行输入三个整数 ai,bi(1≤ai,bi≤m),li(1≤li≤106)a_i,b_i(1 \le a_i, b_i \le m),l_i(1 \le l_i \le 10^6)ai,bi(1≤ai,bi≤m),li(1≤li≤106),分别表示快速路连接的两个城市群编号和边的距离。
最后一行输入 s,t(1≤s,t≤n)s, t(1 \le s, t \le n)s,t(1≤s,t≤n),表示起点和终点城市编号。
输出格式
输出一个整数,表示城市 sss 到城市 ttt 到最短路。如果不存在路径,则输出-1
。
样例说明
1 -> 2 - > 5
或者1 -> 4 -> 5
是最短的路径,总长度为 121212。
样例输入复制
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
暴力建边的话,时间空间都开不下。考虑給每一个城市群添加虚拟结点,不能是双向边,否则城市群内部通过虚拟结点就互联了。
那么我们对于每个城市群开两个虚拟结点in和out,城市群内部每个结点指向out,in指向每个结点,边权为0,两个城市群ab连时out(a)-->in(b),out(b)-->in(a),边权是距离。这些都是有向边。
#include<bits/stdc++.h>
using namespace std;
#define maxn 60000+1000
int n,m,k,m1,m2,s,t;
int in[maxn],out[maxn];
vector<int> group[maxn];
struct Edge{
int from,to,dist;
};
struct HeapNode{
int u;
long long d;
bool operator < (const HeapNode& x)const{
return d>x.d;
}
};
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
long long d[maxn];
void AddEdge(int f,int t,int d)
{
edges.push_back((Edge){f,t,d});
G[f].push_back(edges.size()-1);
}
void dijkstra()
{
priority_queue<HeapNode> Q;
for(int i=0;i<=n;i++)d[i]=(1LL<<50);
d[s]=0;
memset(vis,0,sizeof(vis));
Q.push((HeapNode){s,0});
while(!Q.empty())
{
HeapNode x=Q.top();
Q.pop();
int u=x.u;
if(vis[u])continue;
vis[u]=1;
for(int i=0;i<G[u].size();i++)
{
Edge& e=edges[G[u][i]];
int v=e.to;
if(d[v]>d[u]+e.dist)
{
d[v]=d[u]+e.dist;
Q.push((HeapNode){v,d[v]});
}
}
}
}
int main()
{
// freopen("input.in","r",stdin);
int a,b,c;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>k;
while(k--)cin>>a,group[i].push_back(a);
}
cin>>m1;
while(m1--)
{
cin>>a>>b>>c;
AddEdge(a,b,c);
AddEdge(b,a,c);
}
for(int i=1;i<=m;i++)
{
n++;in[i]=n;
n++;out[i]=n;
for(int j=0;j<group[i].size();j++)AddEdge(in[i],group[i][j],0);
for(int j=0;j<group[i].size();j++)AddEdge(group[i][j],out[i],0);
}
cin>>m2;
while(m2--)
{
cin>>a>>b>>c;
AddEdge(out[b],in[a],c);
AddEdge(out[a],in[b],c);
}
cin>>s>>t;
dijkstra();
if(d[t]==(1LL<<50))cout<<"-1\n";
else cout<<d[t]<<"\n";
return 0;
}