题目链接:LeetCode6032
题意
给定一个有向图,两个起点(s1,s2)和一个终点(dest),要求求出路径最小的带权子图,从两个起点都可以到达终点,且该子图的所有边权之和最小。
思路
- zerotrac(零神yyds)讲得特别好。
- 大体思路就是枚举一个中间节点 a ,求s1到a的最短路,s2到a的最短路,dest到a的最短路,使得路径之和最小。
- 用dijkstra算法,先求出s1,s2到所有点的距离,还有反向图中dest到所有点的距离。
- 这里的dijkstra要用堆优化的dijkstra,朴素的dijkstra不行。
- golang当中的优先队列(或者说堆)操作,相对cpp复杂一点,需要实现接口。
代码(Golang)
type edge struct{
to,weight int
}
const maxx int=int(1e18)
func dij(g [][]edge,source int)[]int{
dis:=make([]int,len(g))
for i:=range dis{
dis[i]=maxx
}
dis[source]=0
h:=hp{{source,0}}
for len(h)>0{
p:=heap.Pop(&h).(pair)
v:=p.v
if dis[v]<p.dis{
continue
}
for _,e:=range g[v]{
to,w:=e.to,e.weight
newDis:=dis[v]+w
if newDis<dis[to]{
dis[to]=newDis
heap.Push(&h,pair{to,newDis})
}
}
}
return dis
}
func minimumWeight(n int, edges [][]int, src1 int, src2 int, dest int) int64 {
g,rg:=make([][]edge,n),make([][]edge,n)
for _,ed:=range edges{
g[ed[0]]=append(g[ed[0]],edge{ed[1],ed[2]})
rg[ed[1]]=append(rg[ed[1]],edge{ed[0],ed[2]})
}
dis1,dis2,dis3:=dij(g,src1),dij(g,src2),dij(rg,dest)
//fmt.Println(dis1,dis2,dis3)
ans:=maxx
for i:=0;i<n;i++{
ans=min(ans,dis1[i]+dis2[i]+dis3[i])
}
if ans<maxx{
return int64(ans)
}
return -1
}
type pair struct{
v,dis int
}
type hp []pair
func (h hp)Len()int {return len(h)}
func (h hp)Less(i,j int)bool{return h[i].dis<h[j].dis}
func (h hp)Swap(i,j int){h[i],h[j]=h[j],h[i]}
func (h*hp)Push(x interface{}){*h=append(*h,x.(pair))}
func (h*hp)Pop()(x interface{}){a:=*h;*h,x=a[:len(a)-1],a[len(a)-1];return}
func min(i,j int)int{
if i>j{
return j
}
return i
}
代码(Cpp)
class Solution {
public:
typedef long long ll;
const ll maxx=1e18;
vector<ll> dij(vector<vector<pair<ll,ll>>>g,int source){
vector<ll>dis(g.size(),maxx);
dis[source]=0;
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;
pq.push({0ll,source});
while(pq.size()>0){
auto now=pq.top();
pq.pop();
ll w=now.first;int to=now.second;
if (dis[to]<w){
continue;
}
for (int i=0;i<g[to].size();i++){
ll v=g[to][i].first,weight=g[to][i].second;
ll nw=dis[to]+weight;
if(nw<dis[v]){
dis[v]=nw;
pq.push({nw,v});
}
}
}
return dis;
}
long long minimumWeight(int n, vector<vector<int>>& edges, int src1, int src2, int dest) {
vector<vector<pair<ll,ll>>>g(n),rg(n);
for(int i=0;i<edges.size();i++){
int u=edges[i][0],v=edges[i][1],w=edges[i][2];
g[u].push_back({v,w});
rg[v].push_back({u,w});
}
vector<ll>dis1,dis2,dis3;
dis1=dij(g,src1);
dis2=dij(g,src2);
dis3=dij(rg,dest);
ll ans=maxx;
for(int i=0;i<n;i++){
ans=min(ans,dis1[i]+dis2[i]+dis3[i]);
}
return ans==maxx?-1:ans;
}
};