ZOJ 3946 Highway Project【dijkstra】【貪心】

題目鏈接

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章