正反两次建边,跑两次最短路。(主要存个最短路的模板)。
#include <iostream> #include <algorithm> #include <queue> #include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int N = 2e6 + 10; ll INF = 1e16+10; ll dis[N],dis1[N]; // 存两点之间的距离 bool via[N]; // 用于标记该点是否已经找到最短路 int n, m, a, b; struct node //结构体存边以及边的权值 { int to; ll dis; friend bool operator<(node n1, node n2) //重载运算 { return n1.dis > n2.dis; } }; vector<node> vec[N],vec1[N]; //用邻接表方式存边,若边较少可使用邻接矩阵存边; priority_queue<struct node> q; //用优先队列实现可降低时间复杂度。 int dijstra(int start,vector<node> vec[]) { memset(via, false, sizeof(via)); dis[start] = 0; node t; t.to = start,t.dis = 0; q.push(t); while (!q.empty()) { node now = q.top(); q.pop(); if (!via[now.to]){ via[now.to] = true; for (int i = 0; i < vec[now.to].size(); i++){ node p=vec[now.to][i]; int to = p.to; ll cost = p.dis + dis[now.to]; //更新与now.to相关联的点的(p.to)的最短路径 if (cost < dis[to]){ //更新 dis[to] = cost; node t; t.to = to,t.dis = cost; q.push(t); } } } } } void init() { for (int i = 1; i <= n; i++){ dis[i] = INF; vec[i].clear(); vec1[i].clear(); } } int main() { int t; cin>>t; while(t--){ cin >> n >> m ; init(); for (int i = 1; i <= m; i++){ int u, v, l; cin >> u >> v >> l; node t; t.dis = l,t.to = v; vec[u].push_back(t); t.dis=l,t.to=u; vec1[v].push_back(t); } dijstra(1,vec); for(int i=1; i<=n; i++) dis1[i]=dis[i]; for(int i=1; i<=n; i++) dis[i]=INF; dijstra(1,vec1); ll sum=0; for(int i=1; i<=n; i++){ //cout<<dis1[i]<<" "<<dis[i]<<endl; sum+=dis1[i]+dis[i]; } cout<<sum<<endl; } return 0; }