题解:P12544 [UOI 2025] Boys and Girls
第一眼看成 ARC200E 了还有救吗。
题目相当于给定一张
菊花是容易的,考虑三元环。对于三元环的三条边
考虑枚举
:::success[AC 代码]
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define MAXN 1400007
using ll = long long;
using pli = pair<ll, int>;
// 加了快读是因为模拟赛开了 1e7(但不影响 n^2 能过)
char buf[1 << 21], *p1, *p2;
inline char gc()
{
if (p1 == p2)
{
p2 = buf + fread(p1 = buf, 1, sizeof(buf), stdin);
}
return *p1++;
}
inline int read()
{
int x = 0;
char ch = gc();
while (ch < '0' || ch > '9')
{
ch = gc();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + (ch ^ '0');
ch = gc();
}
return x;
}
vector<pli> e[MAXN];
ll deg[MAXN];
int n;
ll buc[MAXN];
void solve()
{
n = read();
for (int i = 1; i <= 2 * n; i++)
{
e[i].clear();
deg[i] = 0;
}
for (int i = 1; i <= n; i++)
{
int a = read(), b = read(), c = read();
e[a].emplace_back(c, b);
e[b].emplace_back(c, a);
deg[a] += c;
deg[b] += c;
}
ll res = *max_element(deg + 1, deg + 2 * n + 1);
for (int i = 1; i <= 2 * n; i++)
{
if (e[i].size() < 2)
{
continue;
}
partial_sort(e[i].begin(), e[i].begin() + 2, e[i].end(), greater<pli>());
auto a = e[i][0], b = e[i][1];
if (deg[i] - a.first - b.first >= a.first)
{
continue;
}
for (auto p : e[a.second])
{
buc[p.second] += p.first;
}
for (auto b : e[i])
{
if (b == a)
{
continue;
}
res = max(res, b.first + a.first + buc[b.second]);
}
for (auto p : e[a.second])
{
buc[p.second] = 0;
}
}
cout << res << '\n';
}
int main()
{
int t = read();
while (t--)
{
solve();
}
return 0;
}
虽然通过确实很搞笑。但是卡掉的方法也很容易。注意到这个复杂度应该是
:::
当然有线性做法。观察到刚才做法复杂度爆炸的地方是枚举 vector 里面,这样对每个
:::success[AC Code]{open}
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define MAXN 1400007
using ll = long long;
using pii = pair<int, int>;
char buf[1 << 21], *p1, *p2;
inline char gc()
{
if (p1 == p2)
{
p2 = buf + fread(p1 = buf, 1, sizeof(buf), stdin);
}
return *p1++;
}
inline int read()
{
int x = 0;
char ch = gc();
while (ch < '0' || ch > '9')
{
ch = gc();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + (ch ^ '0');
ch = gc();
}
return x;
}
// 模拟赛卡空间 /kx /kx
struct Edge
{
int u, v, w;
} e[MAXN], g[MAXN];
int eid, gid;
int he[MAXN], hg[MAXN];
ll deg[MAXN];
int n;
int buc[MAXN];
void add(Edge *g, int &gid, int *hg, int u, int v, int w)
{
g[++gid] = {hg[u], v, w};
hg[u] = gid;
}
void solve()
{
n = read();
for (int i = 1; i <= 2 * n; i++)
{
he[i] = 0;
hg[i] = 0;
deg[i] = 0;
}
for (int i = 1; i <= n; i++)
{
int a = read(), b = read(), c = read();
add(e, eid, he, a, b, c);
add(e, eid, he, b, a, c);
deg[a] += c;
deg[b] += c;
}
ll res = *max_element(deg + 1, deg + 2 * n + 1);
for (int i = 1; i <= 2 * n; i++)
{
if (!he[i])
{
continue;
}
int ma = 0;
for (int j = he[i]; j; j = e[j].u)
{
if (e[j].w > e[ma].w)
{
ma = j;
}
}
add(g, gid, hg, e[ma].v, i, e[ma].w);
}
for (int i = 1; i <= 2 * n; i++)
{
if (!hg[i])
{
continue;
}
for (int j = he[i]; j; j = e[j].u)
{
buc[e[j].v] += e[j].w;
}
for (int j = hg[i]; j; j = g[j].u)
{
for (int k = he[g[j].v]; k; k = e[k].u)
{
if (e[k].v != i)
{
res = max(res, ll(e[k].w) + g[j].w + buc[e[k].v]);
}
}
}
for (int j = he[i]; j; j = e[j].u)
{
buc[e[j].v] = 0;
}
}
cout << res << '\n';
}
int main()
{
int t = read();
while (t--)
{
solve();
}
return 0;
}
:::