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

题意:两个人从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

#include

#include

#include

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 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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值