链接
题目链接
思路
最小生成树模版。
易错点:
- 可能有多个不同的联通子图,例如1和n号点在a子图中但是其他子图也有对应的min max数据,所以建议用\(minx[N] , maxx[N]\)的方式记录,其中识别符由find_s这个函数给出。
- 需要用到所有的边,在用完之后才能确定,所以采用全局的记录有联通时的最小值。
代码
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define tin long long
#define itn long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N = 2e5 + 10;
int n, m;
struct edge {
itn fr, to, val;
edge(int fr, int to, int val) {
this->fr = fr;
this->to = to;
this->val = val;
}
bool operator<(edge x)const {
return val > x.val;
}
};
priority_queue<edge>pq;
int s[N],minx[N],maxx[N];
int find_s(int i) {
return s[i] = (s[i] == i) ? s[i] : find_s(s[i]);
}
void merge_s(int a, int b) {
int x = find_s(a), y = find_s(b);
s[x] = s[y];
return;
}
void solve()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)s[i] = i ,minx[i]=LLONG_MAX ,maxx[i]=0;
for (itn i = 1; i <= m; i++) {
int a, b, x; cin >> a >> b >> x;
pq.push(edge(a, b, x));
}
itn ans = LLONG_MAX;
while (!pq.empty()) {
int minn = LLONG_MAX, maxn = 0;
edge now = pq.top();
pq.pop();
minn = min(minx[find_s(now.fr)], minx[find_s(now.to)]),
maxn = max(maxx[find_s(now.fr)], maxx[find_s(now.to)]);
minn = min(minn, now.val), maxn = max(maxn, now.val);
merge_s(now.fr, now.to);
minx[find_s(now.fr)] = minn, maxx[find_s(now.fr)] = maxn;
if (find_s(1) == find_s(n))
{
ans = min(ans, minx[find_s(1)] + maxx[find_s(n)]);
}
}
cout << ans << '\n';
}
signed main() {
IOS;
/**/int t;
cin >> t;
if(t>0)
while (t--)
solve();
else {
for (itn ik = 1; ik < t; ik++) {
cin >> n >> m;
for (itn i = 1; i <= m; i++) {
int a, b, x; cin >> a >> b >> x;
pq.push(edge(a, b, x));
}
if (ik == 12) {
cout << n << ' ' << m << '\n';
while (!pq.empty()) {
edge now = pq.top(); pq.pop();
cout << now.fr << ' ' << now.to << ' ' << now.val << '\n';
}
}
while (!pq.empty())pq.pop();
}
}
return 0;
}