hrbust1339 Touring (Dijkstra最短路径)(邻接表)

时间:2014-04-29 13:33:21   收藏:0   阅读:295

本文出自:http://blog.csdn.net/svitter


题意:两个人从c出发,分别想去a,b旅行,两个城市之间只有一条路,有一个相应的价值。求最小的价值。通行的时候只花费一个价值。

本题目的关键在于优先队列,求出a, b, c到各点的最小价值,然后从中挑选一个点作为分开的点。

dijktra算法时用邻接表存储,因为明显是稀疏图。。还有就是存边的时候记得存双向的边,利用优先队列弹出最小的花费。使用邻接表记得初始化node[i] = -1(可以用memset)


AC:

//============================================================================
// Name        : eee.cpp
// Author      : Vit
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;
#define INF 0x1f1f1f1f

struct str
{
    int num;
    int cost;
    str(int n, int c): num(n), cost(c) {}
    str() {}
    friend bool operator < (str s1, str s2)
    {
        return s1.cost > s2.cost;
    }
};

struct Arc
{
    int next_arc;
    int point;
    int cost;
};

Arc arc[20005]; //两个方向的边
int node[5005];
bool flag[5005];

int lowa[5005];
int lowb[5005];
int lowc[5005];

int m, n;

int c, a ,b;

void dijkstra(int src, int n, int *low)//low表示到每个点的最短距离
{
    memset(flag, 0, sizeof(flag));

    priority_queue <str> q;
    q.push(str(src, 0));
    int kk = 0;
    while(kk < n && !q.empty())
    {
        str s = q.top();
        q.pop();
        if(flag[s.num])
            continue;
        flag[s.num] = 1;
        low[s.num] = s.cost;
        kk++;
        for(int e = node[s.num]; e != -1; e=arc[e].next_arc)
        {
            if(!flag[arc[e].point])
            {
                q.push(str(arc[e].point, arc[e].cost + s.cost));
            }
        }
    }
}


void ace()
{
    //work point
    int i, no = 1;
    int u, v, w;
    while(~scanf("%d%d", &n, &m))
    {
        memset(node, -1, sizeof(node));

        memset(lowa, 0x1f, sizeof(lowa));
        memset(lowb, 0x1f, sizeof(lowb));
        memset(lowc, 0x1f, sizeof(lowc));
        scanf("%d%d%d", &a, &b, &c);
        for(i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &u, &v, &w);

            //头插法建立邻接表
            arc[i].next_arc = node[u];
            arc[i].point = v;
            arc[i].cost = w;
            node[u] = i;

            //反向边(本身无序)
            arc[m + i].next_arc = node[v];
            arc[m + i].point = u;
            arc[m + i].cost = w;
            node[v] = m + i;
        }

        dijkstra(a, n, lowa);
        dijkstra(b, n, lowb);
        dijkstra(c, n, lowc);

        printf("Scenario #%d\n", no++);
        int res = INF;
        int sum;
        for(i = 1; i <= n; i++)//在i处分开
        {
            sum = lowa[i] + lowb[i] + lowc[i];
            if(sum < res)
                res = sum;
        }

        if(res >= INF)
        {
            printf("Can not reah!\n\n");
        }
        else
        {
            printf("%d\n\n", res);
        }
    }
}

int main()
{
    ace();
    return 0;
}


评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!