ZOJ 3946 Highway Project【dijkstra】【贪心】

来源:互联网 发布:淘宝天下传媒 诈骗 编辑:程序博客网 时间:2024/05/21 17:19

题目链接

http://icpc.moe/onlinejudge/showProblem.do?problemId=5718

思路

给你一个无向图,每条边有一个时间c和花费d,叫你选一些边,使得点0到其他所有点的时间之和最小,其次,使总花费最小。

因为要使得点0到其他所有点的时间之和最小,所以是个最短路问题,用dijkstra找最短路,为了让花费最小,更新距离的时候,如果耗时相等,但新边的花费比旧边少的话,也要更新上去。

dis[i].c记录0到i点的最短用时,dis[i].d记录这个点紧连的那条边的花费。

最后答案就是所有dis[i].cdis[i].d的和了。

比赛的时候优先队列里直接放点编号了,然后比较函数又调用了全局的dis,导致运算过程中堆会变的不合法(因为dis会变),这个在VC++里会直接抛出invalid heap 异常。于是弄到最后代码都没成功运行…(总归还是太弱)

AC代码

#include <iostream>#include <queue>#include <vector>#include <cstring>#include <cstdio>using namespace std;typedef long long ll;const int N = 100000 + 100;const int E = 200000 + 100;const ll INF = ((ll)1) << 61;struct edge_t {    int v;    int next;    int c, d;}edge[E];int head[N], tot = 0;void add_edge(int u, int v, int d, int c){    edge[tot].d = d; edge[tot].c = c;    edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++;}struct node{    int u;    ll c,d;    node (){}    node(int uu, int cc, int dd)    {        u=uu;        c=cc;        d=dd;    }    friend bool operator < (const node &a, const node &b)    {        if(a.d==b.d)return a.c>b.c;        return a.d>b.d;    }};bool vis[N];node dis[N];priority_queue<node>q;void dijkstra(){    dis[0].c = 0;    dis[0].d = 0;    q.push(dis[0]);    while (!q.empty())    {        int u = q.top().u; q.pop();        if(vis[u])continue;        vis[u] = 1;        for (int i = head[u]; ~i; i = edge[i].next)if (!vis[edge[i].v])        {            int v = edge[i].v;            if (dis[u].d + edge[i].d < dis[v].d)            {                dis[v].d = dis[u].d + edge[i].d;                dis[v].c = edge[i].c;                q.push(dis[v]);            }            else if (dis[u].d + edge[i].d == dis[v].d&& edge[i].c < dis[v].c)            {                dis[v].d = dis[u].d + edge[i].d;                dis[v].c = edge[i].c;                q.push(dis[v]);            }        }    }}void init(int n){    for (int i = 0; i < n; ++i)    {        dis[i].u = i;        dis[i].c = INF;        dis[i].d = INF;    }    memset(vis, 0, sizeof vis);    tot = 0;    memset(head, -1, sizeof head);    memset(edge, 0, sizeof edge);}int main(){    int T;    scanf("%d", &T);    while (T--)    {        int n, m;        scanf("%d%d", &n, &m);        init(n);        for (int i = 0; i < m; ++i)        {            int u, v, d, c;            scanf("%d%d%d%d", &u, &v, &d, &c);            add_edge(u, v, d, c);            add_edge(v, u, d, c);        }        dijkstra();        ll sum_c = 0, sum_d = 0;        for(int i=0 ; i<n ; ++i)        {            sum_c+=dis[i].c;            sum_d+=dis[i].d;        }        printf("%lld %lld\n", sum_d, sum_c);    }    return 0;}
0 0