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;
}