P4180 严格次小生成树
搞得倍增,11K 自己将就着看吧。
#include <bits/stdc++.h>
#define int long long
#define debug fout << "Debug: " << __LINE__ << endl;
using namespace std;
namespace FastIO
{
struct instream
{
int base = 10;
friend instream &operator>>(instream &in, int &num)
{
int flag = 1;
int ans = 0;
char ch = getchar();
while (ch < '0' || ch > '9')
{
if (ch == '-')
{
flag = -flag;
}
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
ans = ans * in.base + (ch - '0');
ch = getchar();
}
num = ans * flag;
return in;
}
};
struct outstream
{
template<typename _CharT, typename _Traits = char_traits<_CharT>>
struct typ {
typedef basic_ostream<_CharT, _Traits>& (* end) (basic_ostream<_CharT, _Traits>&);
};
int base = 10;
friend outstream &operator<<(outstream &out, int num)
{
if (num < 0)
{
putchar('-');
num = -num;
}
if (num >= 10)
{
out << num / 10;
}
putchar(num % 10 + '0');
return out;
}
friend outstream &operator<<(outstream &out, const char * s) {
printf("%s", s);
return out;
}
friend outstream &operator<<(outstream &out, string s) {
cout << s;
return out;
}
friend outstream &operator<<(outstream &out, typ<char>::end e) {
puts("");
return out;
}
};
instream fin;
outstream fout;
}
using namespace FastIO;
const int maxn = 1e5 + 1;
const int maxm = 6e5 + 1;
const int maxd = 70;
const int inf = 1e15;
struct edge {
int from, to, weight, next;
int mir, org;
};
struct tree {
int n, cnt;
int head[maxn];
edge e[maxm];
int fa[maxn][maxd];
int dep[maxn];
int mn[maxn][maxd], sc[maxn][maxd];
void get_dep(int u, int depth, int fat) {
dep[u] = depth;
for (register int i = head[u]; i; i = e[i].next) {
if (e[i].to != fat) {
get_dep(e[i].to, depth + 1, u);
}
}
}
void get_fa(int cur, int fat) {
fa[cur][0] = fat;
for (register int i = 1; i <= log2(dep[cur]) + 1; ++i) {
fa[cur][i] = fa[fa[cur][i - 1]][i - 1];
}
for (register int i = head[cur]; i; i = e[i].next) {
if (e[i].to != fat) {
get_fa(e[i].to, cur);
}
}
}
void get_mn_sc(int u, int fat) {
for (register int i = 1; i <= log2(dep[u]) + 1; ++i) {
int scond = sc[u][i - 1];
int sconu = sc[fa[u][i - 1]][i - 1];
int mnond = mn[u][i - 1];
int mnonu = mn[fa[u][i - 1]][i - 1];
if (mnond > mnonu) {
sc[u][i] = max(mnonu, max(scond, sconu));
mn[u][i] = mnond;
} else if (mnond < mnonu) {
sc[u][i] = max(mnond, max(scond, sconu));
mn[u][i] = mnonu;
} else {
sc[u][i] = max(scond, sconu);
mn[u][i] = mnonu;
}
}
for (register int i = head[u]; i; i = e[i].next) {
if (e[i].to != fat) {
mn[e[i].to][0] = e[i].weight;
get_mn_sc(e[i].to, u);
}
}
}
int lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
while (dep[u] > dep[v]) {
u = fa[u][(int) log2(dep[u] - dep[v])];
}
if (u == v) return u;
for (register int i = log2(dep[u]); i >= 0; i--) {
if (fa[u][i] != fa[v][i]) {
u = fa[u][i];
v = fa[v][i];
}
}
return fa[u][0];
}
void add_edge(int u, int v, int w) {
e[++cnt] = (edge) {u, v, w, head[u]};
head[u] = cnt;
}
void init() {
get_dep(1, 0, 0);
get_fa(1, 0);
for (register int i = 0; i < maxn; ++i) {
for (register int j = 0; j < maxd; ++j) {
mn[i][j] = sc[i][j] = -inf;
}
}
get_mn_sc(1, 0);
}
void output_e() {
for (register int i = 1; i <= cnt; ++i) {
fout << e[i].from << " " << e[i].to << " " << e[i].weight << endl;
}
}
void output() {
fout << n << endl;
for (register int i = 1; i <= n; ++i) {
fout << dep[i] << " ";
}
fout << endl;
for (register int i = 1; i <= n; ++i) {
for (register int j = 0; j <= log2(dep[i]) + 1; ++j) {
fout << mn[i][j] << " ";
}
fout << endl;
}
fout << endl;
for (register int i = 1; i <= n; ++i) {
for (register int j = 0; j <= log2(dep[i]) + 1; ++j) {
fout << sc[i][j] << " ";
}
fout << endl;
}
}
int jump(int u, int k) {
while (k) {
u = fa[u][(int) (log2(k & -k))];
k -= (k & -k);
}
return u;
}
int get_mn(int u, int v) {
int lca_u_v = lca(u, v);
if (lca_u_v == u) {
int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
int mnv = max(mn[v][lg2v], mn[jump(v, dep[v] - dep[lca_u_v] - (1 << lg2v))][lg2v]);
return mnv;
}
if (lca_u_v == v) {
int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
int mnu = max(mn[u][lg2u], mn[jump(u, dep[u] - dep[lca_u_v] - (1 << lg2u))][lg2u]);
return mnu;
}
int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
int mu = max(mn[u][lg2u], mn[jump(u, dep[u] - dep[lca_u_v] - (1 << lg2u))][lg2u]);
int mv = max(mn[v][lg2v], mn[jump(v, dep[v] - dep[lca_u_v] - (1 << lg2v))][lg2v]);
return max(mu, mv);
}
int get_sc_on_line(int u, int v) { // u is v's fafafafafafa...
if (dep[u] > dep[v]) swap(u, v);
int lg2 = (int) (log2(dep[v] - dep[u]));
int scans;
int mnu = mn[jump(v, dep[v] - dep[u] - (1 << lg2))][lg2];
int mnv = mn[v][lg2];
int scu = sc[jump(v, dep[v] - dep[u] - (1 << lg2))][lg2];
int scv = sc[v][lg2];
if (mnu != mnv) {
scans = max(min(mnu, mnv), max(scu, scv));
} else {
scans = max(scu, scv);
}
return scans;
}
int get_sc(int u, int v) {
if (u == v) return -inf;
int lca_u_v = lca(u, v);
if (lca_u_v == u || lca_u_v == v) {
return get_sc_on_line(u, v);
}
int lg2u = (int) (log2(dep[u] - dep[lca_u_v]));
int lg2v = (int) (log2(dep[v] - dep[lca_u_v]));
int mnu = max(mn[u][lg2u], mn[jump(u, dep[u] - dep[lca_u_v] - (1 << lg2u))][lg2u]);
int mnv = max(mn[v][lg2v], mn[jump(v, dep[v] - dep[lca_u_v] - (1 << lg2v))][lg2v]);
int scu = get_sc_on_line(u, lca_u_v);
int scv = get_sc_on_line(v, lca_u_v);
if (mnu > mnv) {
return max(mnv, max(scu, scv));
} else if (mnu < mnv) {
return max(mnu, max(scu, scv));
} else {
return max(scu, scv);
}
}
};
struct dsu {
int fa[maxn];
void init(int n) {
for (register int i = 1; i <= n; ++i) {
fa[i] = i;
}
}
int find(int x) {
if (fa[x] == x) {
return x;
}
return fa[x] = find(fa[x]);
}
};
tree tr;
struct graph {
int n, m, cnt;
int head[maxn];
edge e[maxm];
edge ee[maxm];
bool intree[maxm];
dsu d;
void add_edge(int u, int v, int w) {
e[++cnt] = (edge) {u, v, w, head[u]};
e[cnt].mir = (cnt % 2 == 1 ? cnt + 1 : cnt - 1);
ee[cnt] = (edge) {u, v, w, head[v], (cnt % 2 == 1 ? cnt + 1 : cnt - 1), cnt};
head[u] = cnt;
}
void init() {
fin >> n >> m;
for (register int i = 1; i <= m; ++i) {
int u, v, w;
fin >> u >> v >> w;
if (u == v) {
w = inf;
}
add_edge(u, v, w);
add_edge(v, u, w);
}
}
int kruskal() {
sort(ee + 1, ee + cnt + 1, [](edge a, edge b) {
return a.weight < b.weight;
});
int ans = 0;
d = dsu();
d.init(n);
tr.n = n;
int qwq_qaq = 0;
for (register int i = 1; i <= cnt; ++i) {
int u = d.find(ee[i].from);
int v = d.find(ee[i].to);
if (u != v) {
qwq_qaq++;
ans += ee[i].weight;
d.fa[u] = v;
intree[ee[i].org] = true;
intree[ee[i].mir] = true;
// cout << ee[i].from << " " << ee[i].to << " " << ee[i].weight << endl;
// cout << ee[i].org << " " << ee[i].mir << endl;
tr.add_edge(ee[i].from, ee[i].to, ee[i].weight);
tr.add_edge(ee[i].to, ee[i].from, ee[i].weight);
if (qwq_qaq == n - 1) break;
}
}
return ans;
}
int second_min_generate_tree() {
int mn = inf;
for (register int i = 1; i <= cnt; ++i) {
if (intree[i]) continue;
if (!(i & 1)) continue;
int u = e[i].from;
int v = e[i].to;
int w = e[i].weight;
// fout << u << " " << v << " " << w << endl;
int mnuv = tr.get_mn(u, v);
int scuv = tr.get_sc(u, v);
// cout << mnuv << " " << scuv << endl;
if (mnuv == -inf) {
if (scuv == -inf) continue;
if (w == mnuv) continue;
mn = min(mn, w - mnuv);
} else {
if (w == mnuv) mn = min(mn, w - scuv);
else mn = min(mn, w - mnuv);
}
}
return (mn == inf ? -1 : mn);
}
};
graph g;
signed main() {
// freopen("ex_tree1.in", "r", stdin);
g.init();
// cout << endl;
int rans = g.kruskal();
// cout << rans << endl;
tr.init();
// tr.output();
// while (true) {
// int u, v;
// cin >> u >> v;
// cout << tr.get_mn(u, v) << " " << tr.get_sc(u, v) << endl;
// }
// cout << tr.sc[6][1] << endl;
// cout << tr.get_mn(2, 4) << endl;
int mn = g.second_min_generate_tree();
if (mn == -1) {
fout << "No Solution!" << endl;
} else {
fout << rans + mn << endl;
}
return 0;
}
/*
5 6
1 4 16
2 4 8
2 5 6
2 3 5
3 4 1
3 5 3
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!