AtCoder Beginner Contest 222(补题)
Posted 佐鼬Jun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AtCoder Beginner Contest 222(补题)相关的知识,希望对你有一定的参考价值。
E - Red and Blue Tree
题目链接: link.
题意:
给一颗 n n n个结点, n − 1 n-1 n−1条边的树,每条边都有可能是红色或者蓝色,边的总颜色方案为 2 n − 1 2^{n-1} 2n−1,现在有一个长度为 m m m的序列, A 1 , . . . . A m A_1,....A_m A1,....Am,现在以 A i A_i Ai为根节点,通过最短路走到 A i + 1 A_{i+1} Ai+1点,最终以每个 A i A_i Ai为根节点跑完路径,算出经过的总红边数和总蓝边数,现在要求总红边数 − - −总蓝边数 = = = K K K,有多少方案满足要求
思路:
把序列
A
i
A_i
Ai跑完,通过
D
F
S
DFS
DFS算出每个边都被计算了几遍,然后把所有的经过次数累加,记为
S
S
S
此时经过的总红边数
+
+
+总蓝边数=
S
S
S
总红边数
−
-
−总蓝边数
=
=
=
K
K
K
此时如果根据两个式子可得,
S
S
S与
K
K
K一定同奇偶,如果不是就矛盾,即没有方案,如果
S
+
K
<
0
S+K<0
S+K<0也是矛盾的,也是没有方案。
如果有解,这两个等式,一定能推出,
总
红
边
数
=
S
+
K
2
总红边数= \\frac{S+K}{2}
总红边数=2S+K,现在问题就转换为,给你每个边被经过的次数,现在让你选出一些数,让它们的总和为总红边数,此时问题就变成了简单的背包模型。跑个
D
P
DP
DP即可
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5 + 10;
const ll mod = 998244353;
typedef pair<int, int> PII;
vector<vector<PII> > e;
vector<int> sum;
ll f[N];
int n, m, k;
bool dfs(int u, int fa, int goal) {
if (u == goal) return 1;
for (auto it : e[u]) {
int v = it.first;
if (v == fa) continue;
if (dfs(v, u, goal)) {
sum[it.second]++;
return 1;
}
}
return 0;
}
int main() {
cin >> n >> m >> k;
vector<int> a;
a.resize(m);
for (int i = 0; i < m; i++) {
cin >> a[i];
a[i]--;
}
e.resize(n);
for (int i = 0; i < n - 1; i++) {
int x, y;
scanf("%d%d", &x, &y);
x--, y--;
e[x].push_back({y, i});
e[y].push_back({x, i});
}
sum.resize(N - 1);
for (int i = 0; i < m - 1; i++) {
dfs(a[i], -1, a[i + 1]);
}
int Sum = 0;
for (int i = 0; i < n - 1; i++) {
Sum += sum[i];
}
if ((Sum + k) % 2 == 1 || Sum < abs(k)) {
puts("0");
return 0;
}
Sum = abs(Sum + k) / 2;
f[0] = 1;
for (int i = 0; i < n - 1; i++) {
for (int j = Sum; j >= sum[i]; j--) {
(f[j] += f[j - sum[i]]) %= mod;
}
}
printf("%lld\\n", f[Sum]);
return 0;
}
F - Expensive Expense
题目链接: link.
题意:
给有 N N N个点的图,有 N − 1 N-1 N−1条有权无向边,并且每个点都有自己的点权,现在一个人要旅行,旅行的费用从S点开始,在E点结束,旅行的总分费用就是S点到E点走最短路径的边权总费用加上E点的点权,现在让你输出 N N N行,每行输出从该点出发旅游,走的路径中费用的最大值。
思路:
由于是 N N N个点的图,且有 N − 1 N-1 N−1条边的连通图,所以这个无向图也是一颗树。对于一课树来说,是有直径的,也就是树中最长的路径,把图中的点权,也转换为边权,也就是对于点 S S S的点权,就当作 S S S点与 S ′ S' S′虚拟点连了一条边,此时求出树的直径,并把树的直径的两个端点求出来,那么此时对于直径端点 u u u和 v v v来说,最长路径一定就是其算出来的直径。对于不是直径端点的点 t t t,其最长路径一定就是 m a x ( d i s [ u ] [ t ] , d i s [ v ] [ t ] ) max(dis[u][t],dis[v][t]) max(dis[u][t],dis[v][t]),这对于树来说这是一定的。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
typedef pair<int, int> PII;
typedef pair<long long, int> PLI;
const int N = 4e5 + 10, M = N * 2;
const ll inf = 0x3f3f3f3f3f3f3f;
int h[M], e[M], ne[M], idx;
ll w[M];
bool vis[M];
ll Dis = -1, cur = -1;
int n;
void clear_graph() {
memset(h, -1, sizeof(h));
idx = 0;
}
void add_edge(int a, int b, int c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
void dfs(int now, int fa, ll d) {
if (d > Dis) {
Dis = d, cur = now;
}
for (int i = h[now]; ~i; i = ne[i]) {
int j = e[i];
ll val = w[i];
if (j == fa) continue;
dfs(j, now, d + val);
}
}
vector<ll> dijkstra(int start) {
vector<ll> dis(n * 2 + 1, inf);
memset(vis, 0, sizeof(vis));
priority_queue<PLI, vector<PLI>, greater<PLI> > q;
q.push({0, start});
dis[start] = 0;
while (q.size()) {
auto t = q.top();
q.pop();
int now = t.second;
ll distance = t.first;
if (vis[now]) continue;
vis[now] = 1;
for (int i = h[now]; ~i; i = ne[i]) {
int j = e[i];
ll val = w[i];
if (dis[j] > dis[now] + val) {
dis[j] = dis[now] + val;
q.push({dis[j], j});
}
}
}
return dis;
}
int main() {
clear_graph();
scanf("%d", &n);
for (int i = 1, a, b, c; i <= n - 1; i++) {
scanf("%d%d%d", &a, &b, &c);
add_edge(a, b, c), add_edge(b, a, c);
}
for (int i = 1, d; i <= n; i++) {
scanf("%d", &d);
add_edge(i, i + n, d);
add_edge(i + n, i, d);
}
int u, v;
dfs(1, -1, (ll)0);
u = cur;
Dis = -1;
dfs(cur, -1, (ll)0);
v = cur;
auto dis1 = dijkstra(u);
auto dis2 = dijkstra(v);
for (int i = 1; i <= n; i++) {
ll cost = -1;
if (i == u - n)
cost = dis2[i];
else if (i == v - n)
cost = dis1[i];
else
cost = max(dis1[i], dis2[i]);
printf("%lld\\n", cost);
}
return 0;
}
To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激
以上是关于AtCoder Beginner Contest 222(补题)的主要内容,如果未能解决你的问题,请参考以下文章
AtCoder Beginner Contest 115 题解