传送门:CCF201609-4 交通规划
1为首都,要求改造的铁路到首都的最短路不变,且其他城市两两高铁互通,故直接对1用dijkstra,算出其他点到1的最短路,此时即满足了以上两个条件。
由于要计算需要改造的长度,如果直接将其他点到1的最短路累加,会出现重复计算的现象,所以需要增加一个c数组,c[i]用来记录点i的前驱到i点的长度,在dijkstra更新时一起更新,最后将c[i]累加即可。但要注意的一点是,dijkstra更新dis数组时,判断的条件是dis[v]>dis[u]+w[u][v],如果存在另一条点p,存在dis[v]==dis[p]+w[p][v],此时我们需要取min(w[u][v], w[p][v]),以达到所需改造的长度最小的目的。
下面上代码:
#include <bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
using namespace std;
const int maxn = 1e4+10;
struct node
{
int x, d;
node() {}
node(int X, int D): x(X), d(D) {}
bool operator < (const node& a) const
{
if(d == a.d)
return x < a.x;
return d > a.d;
}
};
int n, m;
int dis[maxn], c[maxn];
vector<node> r[maxn];
void read()
{
cin >> n >> m;
for(int i = 0; i < m; ++i)
{
int u, v, w;
cin >> u >> v >> w;
r[u].push_back(node(v, w));
r[v].push_back(node(u, w));
}
}
void dijkstra(int s)
{
int vis[maxn] = {0};
priority_queue<node> q;
q.push(node(s, dis[s]));
while(!q.empty())
{
node cur = q.top();
q.pop();
if(vis[cur.x])
continue;
for(int i = 0; i < r[cur.x].size(); ++i)
{
node next = r[cur.x][i];
if(dis[next.x] > dis[cur.x]+next.d)
{
dis[next.x] = dis[cur.x]+next.d;
c[next.x] = next.d;
q.push(node(next.x, dis[next.x]));
}
if(dis[next.x] == dis[cur.x]+next.d)
c[next.x] = min(next.d, c[next.x]);
}
vis[cur.x] = 1;
}
}
void solve()
{
for(int i = 2; i <= n; ++i)
dis[i] = INF;
dis[1] = 0;
dijkstra(1);
int ans = 0;
for(int i = 1; i <= n; ++i)
ans += c[i];
cout << ans;
}
int main()
{
read();
solve();
return 0;
}