CCF201609-4 交通规划(最短路)

传送门: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;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值