https://nanti.jisuanke.com/t/15969
百度地图上有 n 个城市,城市编号依次为 1 到 n。地图中有若干个城市群,编号依次为 1 到 m。每个城市群包含一个或多个城市;每个城市可能属于多个城市群,也可能不属于任何城市群。
地图中有两类道路。第一类道路是 城市之间的快速路,两个城市 u,v 之间增加一条距离为 c的边;第二类道路是 城市群之间的高速路,连接两个城市群 a,b,通过这条高速路,城市群 a里的每个城市与城市群 b 里的每个城市之间两两增加一条距离为 c 的边。图中所有边均为无向边。
你需要计算从城市 s 到城市 t 的最短路。
输入格式
第一行输入 n(1≤n≤20000), m(0≤m≤20000),分别表示城市总数和城市群总数。
接下来一共输入 m 行。
第 i 行首先输入一个 ki(1≤ki≤n),表示第 i 个城市群中的城市数为 ki。接下来输入 ki 个数,表示第 i 个城市群中每个城市的编号(保证一个城市群内的城市编号不重复且合法,∑i=1mki≤20000)。
下一行输入一个整数 m1(0≤m1≤20000),表示有 m1 条第一类道路,即 城市之间的快速路。
接下来 m1 行,每行输入三个整数 ui,vi(1≤ui,vi≤n),ci(1≤ci≤106),分别表示快速路连接的两个城市编号和边的距离。
下一行输入一个整数 m2(0≤m2≤20000),表示有 m2 条第二类道路,即 城市群之间的高速路。
接下来 m2 行,每行输入三个整数 ai,bi(1≤ai,bi≤m),li(1≤li≤106),分别表示快速路连接的两个城市群编号和边的距离。
最后一行输入 s,t(1≤s,t≤n),表示起点和终点城市编号。
输出格式
输出一个整数,表示城市 s 到城市 t 到最短路。如果不存在路径,则输出-1
。
样例说明
1
-> 2 - > 5
或者1
-> 4 -> 5
是最短的路径,总长度为 12。
样例输入
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
其实就是建图有难点,只要会建图,那么就是普通的最短路。把一个城市群分为两个点,一个出点,一个入点,我是映射为i+n和i+n+n.
//https://nanti.jisuanke.com/t/15969
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define maxn 60005
struct node
{
int to;
LL cnt;
friend bool operator< (node n1, node n2)
{
return n1.cnt > n2.cnt;
}
node(){}
node(int a,int b)
{
to=a;
cnt=b;
}
};
vector<node > v[maxn];
vector<int > E[maxn];
LL d[maxn];
int inq[maxn];
void spfa(int s,int t)
{
for(int i=0;i<maxn;i++)
{
d[i]=1e15;
inq[i]=0;
}
queue<int > q;
q.push(s);
d[s]=0;
inq[s]=1;
LL ans=1e15;
while(!q.empty())
{
int now=q.front();
q.pop();
inq[now]=0;
//printf("hah %d %lld\n",now,d[now]);
if(now==t)
{
ans=min(ans,d[now]);
}
for(int i=0;i<v[now].size();i++)
{
int to=v[now][i].to;
int cnt=v[now][i].cnt;
if(d[to]>d[now]+cnt)
{
d[to]=d[now]+cnt;
if(inq[to]==0)
{
inq[to]=1;
q.push(to);
}
}
}
}
if(ans==1e15)
{
printf("-1\n");
}
else
{
printf("%lld\n",ans);
}
}
int main()
{
for(int i=0;i<maxn;i++)
{
v[i].clear();
}
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int k;
scanf("%d",&k);
while(k--)
{
int a;
scanf("%d",&a);
v[i+n].push_back(node(a,0));
v[a].push_back(node(i+n+n,0));
}
}
int k;
scanf("%d",&k);
while(k--)
{
int a,b;
LL c;
cin>>a>>b>>c;
v[a].push_back(node(b,c));
v[b].push_back(node(a,c));
}
scanf("%d",&k);
while(k--)
{
int a,b;
LL c;
cin>>a>>b>>c;
v[a+n+n].push_back(node(b+n,c));
v[b+n+n].push_back(node(a+n,c));
}
int s,t;
cin>>s>>t;
spfa(s,t);
return 0;
}