PAT1 1003 Emergency

题目链接
我的github

题目大意

给一张无向图,图上每个点都有一个点权,有些点之间有边相连,且每条边有边权,现在给起点和终点,要求找出所有的路径满足从起点到终点的边权和最小,这些路径中点权和最大值

输入

每个输入包含一个测试用例,每个用例的第一行有4个正整数 N , M , C 1 , C 2 N, M, C_1, C_2 N,M,C1,C2
N ( N ≤ 500 ) N(N \leq 500) NN500是点的数量(从0~ N − 1 N-1 N1)
M M M是边的数量
C 1 C_1 C1起点
C 2 C_2 C2终点
第二行有 N N N个整数,第 i i i个数表示第 i i i个点的点权
接着有 M M M行,每行有三个整数 c 1 , c 2 , L c_1, c_2, L c1,c2,L,表示 c 1 c 2 c_1c_2 c1c2两个点之间的边权是 L L L

输出

对于每个测试样例输出起点和终点之间边值和最小的路径的条数和这些路径中权值和最大的值,并以一行输出

样例输入

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

样例输出

2 4

解析

这题可以用dijkstra算法去解,dis[i]保存起点到i的最小边权和,value[i]保存起点到i的最大点权和,weight[i]保存每个点的点权,num[i]表示起点到i的最短路径的条数,vis[i]表示i点是否访问过,edge[i][j]保存ij之间的边权。
每次出现dis[mark] + edge[mark][j] < dis[j]时,更新disnumvalue
如果出现dis[mark] + edge[mark][j] == dis[j]时,更新num,如果同时还有value[mark] + weight[j] > value[j],则更新value

INF = 0xffffffff    #无穷大
n, m, c1, c2 = map(int, input().split())
weight = list(map(int, input().split()))
value = [INF for i in range(n)]
value[c1] = weight[c1]
dis = [INF for i in range(n)]
dis[c1] = 0    #将起点与起点的距离设为0
num = [0] * n
num[c1] = 1
vis = [False for i in range(n)]
edge = [[INF for i in range(n)] for j in range(n)]
for i in range(m):
    a, b, c = map(int, input().split())
    edge[a][b] = edge[b][a] = c
for i in range(n):
    mark = -1
    minn = INF
    for j in range(n):   #找出当前距离起点最近的点
        if vis[j] == False and dis[j] < minn:
            mark = j
            minn = dis[j]
    if mark == -1 or mark == c2:   #如果没找到或者找到的点是终点
        break
    vis[mark] = True    #将找到的点标记为已访问
    for j in range(n):
        if vis[j] == False and edge[mark][j] != INF:   #如果点没有访问过并且标记的点和这个点之间有边
            if dis[mark] + edge[mark][j] < dis[j]:
                dis[j] = dis[mark] + edge[mark][j]
                num[j] = num[mark]
                value[j] = value[mark] + weight[j]
            elif dis[mark] + edge[mark][j] == dis[j]:
                num[j] = num[j] + num[mark]
                if value[mark] + weight[j] > value[j]:
                    value[j] = value[mark] + weight[j]
print("%d %d" % (num[c2], value[c2]))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值