PAT 天梯赛真题集(L2、L3)

题意:求点权最大的最短路,输出最短路径条数、点权值、以及最大点权的路径。

做法:Dijstra求最短路,两步:1.找最小点;2.更新路径。这题的1不变,变的是2。在更新新路径的时候,如果找到更短的路径,那么更新点权、方案数;如果路径和最短路径一样,那么比较谁的点权大,更新为点权大的结果。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

#include <bits/stdc++.h>

#define scf0(a) scanf("%s",&a)

#define scf1(a) scanf("%d",&a)

#define scf2(a,b) scanf("%d%d",&a,&b)

#define scf3(a,b,c) scanf("%d%d%d",&a,&b,&c)

#define scf4(a,b,c,d) scanf("%d%d%d%d",&a,&b,&c,&d)

#define MEM(a,b) memset(a,b,sizeof(a))

#define pii pair<int,int>

#define pdd pair<double,double>

#define LL long long

using namespace std;

const int maxn = 500 + 5;

const int INF = 0x3f3f3f3f;

int n, m, s, d;

int u, v, len;

int val[maxn];

int mp[maxn][maxn];

void Dijstra(){

    bool vis[maxn];

    MEM(vis, false);

    int dist[maxn];  //当前点的最短距离

    MEM(dist, INF);

    int tot_val[maxn];   //当前点的最大点权

    MEM(tot_val, 0);

    tot_val[s] = val[s];

    dist[s] = 0;

    vis[s] = true;

    int diff[maxn];  //当前点不同最短路径方案数

    for(int i = 0; i <= n; i++) diff[i] = 1;  //方案数都为1

    map<int,int>fa;  //记录路径

    fa.clear();

    fa[s] = -1;

    for(int i = 0; i < n; i++) {

        if(i != s && dist[i] < INF) {

            dist[i] = mp[s][i];

            tot_val[i] = val[s] + val[i];

            fa[i] = s;

        }

    }

    for(int k = 0; k < n - 1; k++){  //找 n-1 个点

        int minn = INF, pos;

        for(int i = 0; i < n; i++) {

            if(vis[i] == false) {

                if(dist[i] < minn) {

                    minn = dist[i];

                    pos = i;

                }

            }

        }

        vis[pos] = true;

//        cout << pos  << endl;

        for(int i = 0; i < n; i++) {

            if(vis[i] == false) {

                if(dist[pos] + mp[pos][i] < dist[i]) {

                    dist[i] = dist[pos] + mp[pos][i];

                    tot_val[i] = tot_val[pos] + val[i];

                    fa[i] = pos;

                    diff[i] = diff[pos];  //开始写成diff[i] = 1,WA了7分,应该继pos的路径数才对啊!

                }

                else if(dist[pos] + mp[pos][i] == dist[i]) {

                    diff[i] += diff[pos];      //开始写成diff[i]++, WA了7分,应该继pos的路径数才对啊!

                    if(tot_val[i] < tot_val[pos] + val[i]){

                        tot_val[i] = tot_val[pos] + val[i];

                        fa[i] = pos;

                    }

                }

            }

        }

    }

    //输出

    cout << diff[d] << ‘ ‘;

    stack<int>sta;

    int sum = val[d];

    sta.push(d);

    while(fa[d] != -1) {

        d = fa[d];

        sum += val[d];

        sta.push(d);

    }

    cout << sum << endl;

    bool cnt = false;

    while(!sta.empty()) {

        if(cnt) cout << ‘ ‘;cnt = true;

        cout << sta.top();

        sta.pop();

    }

    cout << endl;

}

int main() {

    MEM(mp, INF);

    scf4(n, m, s, d);

    for(int i = 0; i < n; i++) scf1(val[i]);

    for(int i = 0; i < m; i++) {

        scf3(u, v, len);

        mp[u][v] = min(mp[u][v], len); //数据最终不卡相同路径值,但要注意这一点

        mp[v][u] = mp[u][v];

    }

    Dijstra();

}

时间: 2024-08-05 01:36:57

PAT 天梯赛真题集(L2、L3)的相关文章

中国石油大学天梯赛真题模拟第六场

L2-4 链表去重 (25 分) 给定一个带整数键值的链表 L,你需要把其中绝对值重复的键值结点删掉.即对每个键值 K,只有第一个绝对值等于 K 的结点被保留.同时,所有被删除的结点须被保存在另一个链表上.例如给定 L 为 21→-15→-15→-7→15,你需要输出去重后的链表 21→-15→-7,还有被删除的链表 -15→15. 输入格式: 输入在第一行给出 L 的第一个结点的地址和一个正整数 N(≤10?5??,为结点总数).一个结点的地址是非负的 5 位整数,空地址 NULL 用 -1

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告

2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh童鞋的提醒. 勘误2:第7题在推断连通的时候条件写错了,后两个if条件中是应该是<=12 落了一个等于号.正确答案应为116. 1.煤球数目 有一堆煤球.堆成三角棱锥形.详细: 第一层放1个, 第二层3个(排列成三角形), 第三层6个(排列成三角形), 第四层10个(排列成三角形). -. 假设一共

[暑假集训]区域赛套题集

2014-07-03 [浙江第11届省赛]ZOJ 3785 What day is that day?  (打表找循环节) [暑假集训]区域赛套题集

2017年ICPC中国大陆区域赛真题(下)

2017年ICPC中国大陆区域赛真题(下) A - Lovers #include <bits/stdc++.h> using namespace std; const int maxn=2e5+10; int n,k,a[maxn],b[maxn],ans; int main() { int _; scanf("%d", &_); while (_--) { scanf("%d%d", &n, &k); for (int i =

PAT天梯赛练习题 L3-002. 堆栈(线段树查询第K大值)

L3-002. 堆栈 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有“入栈”(将新元素插入栈顶)和“出栈”(将栈顶元素的值返回并从堆栈中将其删除).现请你实现一种特殊的堆栈,它多了一种操作叫“查中值”,即返回堆栈中所有元素的中值.对于N个元素,若N是偶数,则中值定义为第N/2个最小元:若N是奇数,则中值定义为第(N+1)/2个最小元. 输入格式: 输入第一行给出正整

PAT天梯赛练习题 L3-010. 是否完全二叉搜索树(完全二叉树的判断)

L3-010. 是否完全二叉搜索树 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 将一系列给定数字顺序插入一个初始为空的二叉搜索树(定义为左子树键值大,右子树键值小),你需要判断最后的树是否一棵完全二叉树,并且给出其层序遍历的结果. 输入格式: 输入第一行给出一个不超过20的正整数N:第二行给出N个互不相同的正整数,其间以空格分隔. 输出格式: 将输入的N个正整数顺序插入一个初始为空的二叉搜索树.在第一行中输出结果树的层序

算法笔记_111:第五届蓝桥杯软件类省赛真题(Java本科A组)试题解答

 目录 1 猜年龄 2 李白打酒 3 神奇算式 4 写日志 5 锦标赛 6 六角填数 7 绳圈 8 兰顿蚂蚁 9 斐波那契 10 波动数列   前言:以下试题解答代码部分仅供参考,若有不当之处,还请路过的同学提醒一下~ 1 猜年龄 标题:猜年龄 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍".小明又补充说:"她们可不是双胞胎,年龄差肯定也不超过8岁啊." 请你写出:小明的较小的妹妹的年龄. 注意: 只写一个人的年龄数

2015年第六届蓝桥杯省赛真题(自己已懂的题目)

1.问题描述:奖券数目 有些人很迷信数字,比如带"4"的数字,认为和"死"谐音,就觉得不吉利. 虽然这些说法纯属无稽之谈,但有时还要迎合大众的需求.某抽奖活动的奖券号码是5位数(10000-99999), 要求其中不要出现带"4"的号码,主办单位请你计算一下,如果任何两张奖券不重号,最多可发出奖券多少张. 请提交该数字(一个整数),不要写任何多余的内容或说明性文字. 思路:5重循环,第一重为1-9,其余为0-9(这样就可以遍历10000到9999

2016河南省第九届ACM程序设计竞赛【正式赛真题】

A题:表达式求值 时间限制:1000 ms  |  内存限制:65535 KB 描述 假设表达式定义为:1. 一个十进制的正整数 X 是一个表达式.2. 如果 X 和 Y 是 表达式,则 X+Y, X*Y 也是表达式; *优先级高于+.3. 如果 X 和 Y 是 表达式,则 函数 Smax(X,Y)也是表达式,其值为:先分别求出 X ,Y值的各位数字之和,再从中选最大数.4.如果 X 是 表达式,则 (X)也是表达式.例如:表达式 12*(2+3)+Smax(333,220+280) 的值为 6