[AOJ 2249]Road Construction[dijkstra]

来源:互联网 发布:php能实现js定时器 编辑:程序博客网 时间:2024/05/19 16:28
题目链接:[AOJ 2249]Road Construction[dijkstra]

题意分析:

N个点,M条边的一张图,给出每条边的距离,和建边的消耗。现在问:保持图中结点1到其它点的最短距离不变,删除掉一些边,那么构建出整张图所需要的消耗最少为多少?

解题思路:

dijkstra在寻找答案的时候我们可以用一个cost数组,记录这个结点入边的最小消耗,最终将最小消耗相加就是我们要求的答案了。

因为最终的图,除了出发点,其它点入边只有一条,所以不存在cost数组重复的情况。

那么根据定义,当距离被更新时,直接更新cost,当距离相等时,更新cost,即可。

个人感受:

第一版本把cost设为了出边的最小消耗,错误,由于出边有多条,这么记录不行。第二版换成先dijkstra再kruskal,然而无法解决保持原有的最短距离。然后和队友讨论,才知道记录入边才是正解。学习了。

具体代码如下:

#include<algorithm>#include<cctype>#include<cmath>#include<cstdio>#include<cstring>#include<iomanip>#include<iostream>#include<map>#include<queue>#include<set>#include<sstream>#include<stack>#include<string>#define ll long long#define pii pair<int, int>#define pr(x) cout << #x << " = " << (x) << '\n';using namespace std;const int INF = 0x7f7f7f7f;const int N = 1e4 + 111;const int M = 4e4 + 111;struct E {    int nxt, to, d, c;}edge[M];int dis[N], cost[N], head[N], cnt;void add_edge(int u, int v, int d, int c) {    edge[cnt].to = v;    edge[cnt].c = c;    edge[cnt].d = d;    edge[cnt].nxt = head[u];    head[u] = cnt++;}void dijkstra(int s) {    dis[s] = 0;    priority_queue<pii, vector<pii>, greater<pii> > pq;    pq.push(pii(dis[s], s));    while (pq.size()) {        pii cur = pq.top(); pq.pop();        int u = cur.second, dist = cur.first;        if (dis[u] < dist) continue;        for (int i = head[u]; ~i; i = edge[i].nxt) {            int v = edge[i].to;            if (dis[v] > dis[u] + edge[i].d) {                dis[v] = dis[u] + edge[i].d;                pq.push(pii(dis[v], v));                cost[v] = edge[i].c;            }            else if (dis[v] == dis[u] + edge[i].d) { // 路径长度相同,比较花费                if (cost[v] > edge[i].c) {                    cost[v] = edge[i].c;                }            }        }    }}int main(){    #ifdef LOCAL    freopen("C:\\Users\\apple\\Desktop\\in.txt", "r", stdin);    #endif    int n, m;    while (~scanf("%d%d", &n, &m) && (n | m)) {        cnt = 0;        int u, v, d, c;        for(int i = 1; i <= n; ++i) {            head[i] = -1;            cost[i] = dis[i] = INF;        }        for (int i = 0; i < m; ++i) {            scanf("%d%d%d%d", &u, &v, &d, &c);            add_edge(u, v, d, c);            add_edge(v, u, d, c);        }        dijkstra(1);        int sum = 0;        for (int i = 1; i <= n; ++i) {            if (cost[i] != INF) sum += cost[i];        }        printf("%d\n", sum);    }    return 0;}


0 0
原创粉丝点击