题目:
题意:
从节点 0 出发,把每一个节点都经过一遍,然后从一个节点回到学校。
由于有 n+1个节点,n条边,而且保证两两互相到达,那么这就是一个棵树。
于是,可以发现,如果从一个点出发,然后回到原来的点,路程是所有边的2倍,这样,就可以枚举从哪个点回学校就行了。
然后一个坑点就是,那个最后枚举的时候ans初始化要注意很大,因为每条边的权值都是10的9次方大小。

1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include <queue> 6 7 using namespace std; 8 9 const int maxn = 100005; 10 11 int times[maxn]; 12 13 struct Edge { 14 int from,to; 15 long long dist; 16 }; 17 18 19 struct Hope { 20 int u; 21 long long d; 22 bool operator < (const Hope& rhs) const { 23 return d > rhs.d; 24 } 25 }; 26 27 28 29 struct Dij { 30 int n,m; 31 vector<int> G[maxn]; 32 vector<Edge> edges; 33 bool vis[maxn]; 34 long long d[maxn]; 35 36 void init(int n) { 37 for(int i=0;i<n;i++) 38 G[i].clear(); 39 edges.clear(); 40 } 41 42 void AddEdge (int from,int to,long long dist) { 43 edges.push_back((Edge){from,to,dist}); 44 m = edges.size(); 45 G[from].push_back(m-1); 46 } 47 48 void dij(int s) { 49 memset(vis,0,sizeof(vis)); 50 memset(d,0x3f3f3f3f,sizeof(d)); 51 52 d[s] = 0; 53 //vis[s] = 1; 54 priority_queue<Hope> Q; 55 Q.push((Hope){s,0}); 56 while(!Q.empty()) { 57 Hope x = Q.top();Q.pop(); 58 if(vis[x.u]) 59 continue; 60 vis[x.u] = true; 61 for(int i=0;i<G[x.u].size();i++) { 62 Edge& e = edges[G[x.u][i]]; 63 if(d[e.to]>d[x.u]+e.dist) { 64 d[e.to] = d[x.u] + e.dist; 65 Q.push((Hope){e.to,d[e.to]}); 66 } 67 } 68 } 69 } 70 71 }; 72 73 Dij sol; 74 75 int main(int argc, char** argv) { 76 int n; 77 scanf("%d",&n); 78 sol.init(n+1); 79 for(int i=0;i<n+1;i++) 80 scanf("%lld",×[i]); 81 long long sum = 0; 82 for(int i=0;i<n;i++) { 83 int from,to; 84 long long dist; 85 scanf("%d%d%lld",&from,&to,&dist); 86 sum+=dist; 87 sol.AddEdge(from,to,dist); 88 sol.AddEdge(to,from,dist); 89 } 90 91 sol.dij(0); 92 sum*=2; 93 94 long long ans = 2000000000; 95 for(int i=0;i<=n;i++) { 96 ans = min(ans,sum-sol.d[i]+(long long)times[i]); 97 } 98 printf("%lld ",ans); 99 return 0; 100 }