2024/9/22_&_9/28 CSP-S daimayuan模拟赛复盘
2024/9/22_&_9/28 daimayuan
Day 5 A. 距离
题面描述
你有一个图,其中有
个点和 条有向边,并且每个点有个权值 。 除了这
条有向边外,如果对于图中两个点 ,有 (即二进制下的与运算),那么会有一条额外的从 到 的有向边。 现在求
号点,到其他所有点的最短距离,也就是经过的最少的有向边数。
输入 & 输出 & 样例 & 数据范围
输入第一行,两个整数
。 接下来一行一共
个数 。 接下来
行,每行两个数 ,表示一条有向边。 输出一共
行,其中第 行表示到 号点的距离。如果无法到达,那么输出 。 对于所有数据,保证
。
5 2
5 4 2 3 7
1 4
2 3
0
1
2
1
-1
思路解析
首先我们把加边的条件转换一下,即
我们用上面加边的方法给值域内的所有值都连好边后,此时我们就有了两张图,一张是题目给的原图,另外一张就是我们在值域上建的这张图,我们考虑如何把两张图联系起来。我们考虑对于原图的每一个
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1.3e6 + 10;
int n, m, a[N], dis[N];
vector<int> g1[N], g2[N];
int main() {
cin >> n >> m;
for(int i = 1; i <= n; i++) {
cin >> a[i];
g1[i].push_back(n + a[i] + 1); g2[n + a[i] + 1].push_back(i);
}
for(int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
g1[u].push_back(v);
}
for(int i = 0; i < (1 << 20); i++) {
for(int j = 0; j < 20; j++) {
if((i >> j) & 1) {
g2[n + i + 1].push_back(n + i + 1 - (1 << j));
}
}
}
memset(dis, 0x3f, sizeof(dis)); dis[1] = 0;
deque<int> q; q.push_back(1);
while(!q.empty()) {
int u = q.front(); q.pop_front();
for(auto v : g1[u]) {
if(dis[v] > dis[u] + 1) {
dis[v] = dis[u] + 1;
q.push_back(v);
}
}
for(auto v : g2[u]) {
if(dis[v] > dis[u]) {
dis[v] = dis[u];
q.push_front(v);
}
}
}
for(int i = 1; i <= n; i++) {
if(dis[i] < 0x3f3f3f3f) cout << dis[i] << '\n';
else puts("-1");
}
return 0;
}
Day 6 A. 伐木
题面描述
你有一棵
个点的树。你可以选择两个不同的点 ,把这两个点的简单路径上的点 包括 删除。对于一条边 ,如果其中任意一个端点在简单路径上,这条边也会被删除。 整棵树会变成若干个连通块。你希望最大化点数大于等于
的连通块个数。
输入 & 输出 & 样例 & 数据范围
输入多组测试数据,第一行一个整数
表示数据组数。对于每组测试数据: 第一行两个整数
。 接下来
行,每行两个数,表示一条树上的边。 输出对于每组测试数据,输出一个数,表示最大值。
对于所有数据,保证
。
2
7 3
1 2
2 3
3 4
4 5
5 6
6 7
9 3
1 2
1 3
1 4
4 5
4 6
4 7
7 8
7 9
1
2
思路解析
问题在树上,是求最大贡献的问题,考虑树形 dp。记
考虑如何统计答案。由于最终的答案链有可能是经过
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int T, n, k, ans = 0, sz[N], f[N];
vector<int> g[N];
void dfs(int u, int fa) {
sz[u] = 1;
for(auto v : g[u]) {
if(v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
}
int cnt = 0, mx1 = -2e9, mx2 = -2e9;
for(auto v : g[u]) {
if(v == fa) continue;
cnt += (sz[v] >= k);
if(f[v] > mx1) mx2 = mx1, mx1 = f[v];
else if(f[v] > mx2) mx2 = f[v];
}
f[u] = cnt + max(0, mx1) - (sz[u] >= k);
ans = max(ans, cnt + mx1 + max(0, mx2) + ((n - sz[u]) >= k));
}
int main() {
cin >> T;
while(T--) {
cin >> n >> k;
memset(f, 0, (n + 5) * sizeof(int)); ans = 0;
for(int i = 1; i <= n; i++) g[i].clear();
for(int i = 1, u, v; i <= n - 1; i++) {
cin >> u >> v;
g[u].push_back(v); g[v].push_back(u);
}
dfs(1, 0);
cout << ans << '\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人