P8817 求助
  • 板块题目总版
  • 楼主zhangzhanrui
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/8/14 17:22
  • 上次更新2023/11/3 03:50:14
查看原帖
P8817 求助
1034711
zhangzhanrui楼主2023/8/14 17:22

[CSP-S 2022] 假期计划

题目描述

小熊的地图上有 nn 个点,其中编号为 11 的是它的家、编号为 2,3,…,n2, 3, \ldots, n 的都是景点。部分点对之间有双向直达的公交线路。如果点 xx 与 z1z_1、z1z_1 与 z2z_2、……、zk−1z_{k - 1} 与 zkz_k、zkz_k 与 yy 之间均有直达的线路,那么我们称 xx 与 yy 之间的行程可转车 kk 次通达;特别地,如果点 xx 与 yy 之间有直达的线路,则称可转车 00 次通达。

很快就要放假了,小熊计划从家出发去 44 个不同的景点游玩,完成 55 段行程后回家:家 →\to 景点 A →\to 景点 B →\to 景点 C →\to 景点 D →\to 家且每段行程最多转车 kk 次。转车时经过的点没有任何限制,既可以是家、也可以是景点,还可以重复经过相同的点。例如,在景点 A →\to 景点 B 的这段行程中,转车时经过的点可以是家、也可以是景点 C,还可以是景点 D →\to 家这段行程转车时经过的点。

假设每个景点都有一个分数,请帮小熊规划一个行程,使得小熊访问的四个不同景点的分数之和最大。

输入格式

第一行包含三个正整数 n,m,kn, m, k,分别表示地图上点的个数、双向直达的点对数量、每段行程最多的转车次数。

第二行包含 n−1n - 1 个正整数,分别表示编号为 2,3,…,n2, 3, \ldots, n 的景点的分数。

接下来 mm 行,每行包含两个正整数 x,yx, y,表示点 xx 和 yy 之间有道路直接相连,保证 1≤x,y≤n1 \le x, y \le n,且没有重边,自环。

输出格式

输出一个正整数,表示小熊经过的 44 个不同景点的分数之和的最大值。

样例 #1

样例输入 #1

8 8 1
9 7 1 8 2 3 6
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 1

样例输出 #1

27

样例 #2

样例输入 #2

7 9 0
1 1 1 2 3 4
1 2
2 3
3 4
1 5
1 6
1 7
5 4
6 4
7 4

样例输出 #2

7

提示

【样例解释 #1】

当计划的行程为 1→2→3→5→7→11 \to 2 \to 3 \to 5 \to 7 \to 1 时,44 个景点的分数之和为 9+7+8+3=279 + 7 + 8 + 3 = 27,可以证明其为最大值。

行程 1→3→5→7→8→11 \to 3 \to 5 \to 7 \to 8 \to 1 的景点分数之和为 2424、行程 1→3→2→8→7→11 \to 3 \to 2 \to 8 \to 7 \to 1 的景点分数之和为 2525。它们都符合要求,但分数之和不是最大的。

行程 1→2→3→5→8→11 \to 2 \to 3 \to 5 \to 8 \to 1 的景点分数之和为 3030,但其中 5→85 \to 8 至少需要转车 22 次,因此不符合最多转车 k=1k = 1 次的要求。

行程 1→2→3→2→3→11 \to 2 \to 3 \to 2 \to 3 \to 1 的景点分数之和为 3232,但游玩的并非 44 个不同的景点,因此也不符合要求。

【数据范围】

对于所有数据,保证 5≤n≤25005 \le n \le 2500,1≤m≤100001 \le m \le 10000,0≤k≤1000 \le k \le 100,所有景点的分数 1≤si≤10181 \le s_i \le {10}^{18}。保证至少存在一组符合要求的行程。

测试点编号n≤n \lem≤m \lek≤k \le
1∼31 \sim 31010202000
4∼54 \sim 51010202055
6∼86 \sim 820205050100100
9∼119 \sim 113003001000100000
12∼1412 \sim 1430030010001000100100
15∼1715 \sim 1725002500100001000000
18∼2018 \sim 20250025001000010000100100

我的代码如下

#include<bits/stdc++.h>
using namespace std;
vector<int> g[2510] , ng[2510];
long long n , m , k , a[2510] , dp[2510] , ans;
int col[2510] , ac[2510][2510];
void bfs(int x) {
    queue<int> q;
    q.push(x);
    memset(ac[x], 63, sizeof(ac[x]));
    ac[x][x] = 0;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = 0; i < g[u].size(); ++i) {
    		int v = g[u][i];
    		if (ac[x][v] > ac[x][u] + 1) {
        		ac[x][v] = ac[x][u] + 1;
        		q.push(v);
    		}
		}
    }
}
long long dfs(int x , int d) {
    if (dp[x] != -1) return dp[x];
    dp[x] = -5000000000000000000ll;
    if (d == 4) {
        if (ac[1][x] <= k + 1) dp[x] = a[x]; else dp[x] = -5000000000000000000ll;
        return dp[x];
    }
    for (int i = 0; i < ng[x].size(); ++i) {
    	int y = ng[x][i];
    	if (col[y] == d + 1) dp[x] = max(dp[x], dfs(y, d + 1) + a[x]);
	}
    return dp[x];
}
int main() {
    srand(1145141);
    cin >> n >> m >> k;
    for (int i = 2; i <= n; ++i) cin >> a[i];
    for (int i = 1, u, v; i <= m; i++) {
        cin >> u >> v;
        g[u].push_back(v) , g[v].push_back(u);
    }
    for (int i = 1; i <= n; ++i) bfs(i);
    for (int i = 1; i <= n; ++i) for (int j = i + 1; j <= n; ++j) if (ac[i][j] <= k + 1) ng[i].push_back(j) , ng[j].push_back(i);
    for (int j = 0; j < 200; ++j) {
        if (rand() % 3 == 1) rand();
        for (int i = 2; i <= n; ++i) col[i] = rand() % 4 + 1;
        memset(dp, -1, sizeof(dp));
        dfs(1, 0);
        ans = max(ans, dp[1]);
    }
    cout << ans;
}

样例一有问题

我的输出

25

求帮助

2023/8/14 17:22
加载中...