10065. 「一本通 3.1 例 2」北极通讯网络
#include <bits/stdc++.h>
using namespace std;
const int N = 500005;
int fa[N], n, k, ind;
double x[N], y[N];
void init() {
for (int i = 0; i <= n; i++) fa[i] = i;
}
int find(int p) { return (p == fa[p]) ? (p) : (fa[p] = find(fa[p])); }
void merge(int p, int q) {
p = find(p);
q = find(q);
fa[p] = q;
}
double dist(double x1, double y1, double x2, double y2) {
return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2));
}
struct Edge {
int u, v;
double w;
bool operator<(const Edge &b) { return w < b.w; }
} e[N];
double ans = 0;
int cnt = 0;
int main() {
// ios::sync_with_stdio(false);
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> x[i] >> y[i];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j < i; j++) {
Edge tmp;
tmp.u = i;
tmp.v = j;
tmp.w = dist(x[i], y[i], x[j], y[j]);
e[++ind] = tmp;
}
}
sort(e + 1, e + ind + 1);
init();
for (int i = 1; i <= ind; i++)
if (find(e[i].u) != find(e[i].v)) {
merge(e[i].u, e[i].v);
++cnt;
if (cnt + k <= n)
ans = max(ans, e[i].w);
}
cout << setiosflags(ios::fixed) << setprecision(2) << ans << endl;
}
10066. 「一本通 3.1 练习 1」新的开始
#include <bits/stdc++.h>
using namespace std;
int n, p[1005][1005], ans, dis[1005];
int main() {
ios::sync_with_stdio(false);
cin >> n;
dis[n + 1] = 1e+9;
for (int i = 1; i <= n; i++) cin >> dis[i];
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) cin >> p[i][j];
for (int i = 1; i <= n; i++) {
int mx = n + 1;
for (int j = 1; j <= n; j++)
if (dis[j] && dis[mx] > dis[j])
mx = j;
ans += dis[mx];
for (int j = 1; j <= n; j++) dis[j] = min(dis[j], p[mx][j]);
}
cout << ans << endl;
}
10067. 「一本通 3.1 练习 2」构造完全图
安全边定理的运用
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n, m, fa[100005], siz[100005], ans;
ll find(ll p) { return p == fa[p] ? p : (fa[p] = find(fa[p])); }
void merge(ll p, ll q) {
p = find(p);
q = find(q);
if (p > q)
swap(p, q);
siz[p] += siz[q];
fa[q] = p;
}
struct Edge {
ll u, v, w;
bool operator<(const Edge &b) { return w < b.w; }
} e[100005];
int main() {
cin >> n;
for (ll i = 1; i < n; i++) {
ll u, v, w;
cin >> u >> v >> w;
Edge t;
t.u = u;
t.v = v;
t.w = w;
e[i] = t;
}
sort(e + 1, e + n);
for (ll i = 1; i <= n; i++) fa[i] = i, siz[i] = 1;
for (ll i = 1; i < n; i++) {
ans += siz[find(e[i].u)] * siz[find(e[i].v)] * (e[i].w + 1);
merge(e[i].u, e[i].v);
}
cout << ans - n + 1 << endl;
}
10068. 「一本通 3.1 练习 3」秘密的牛奶运输
#include <bits/stdc++.h>
using namespace std;
#define N 1000005
#define ll long long
struct Edge {
ll u, v, w;
bool operator<(const Edge &b) { return w < b.w; }
} e[N];
ll n, m, ans, fa[N];
ll find(ll p) { return p == fa[p] ? p : (fa[p] = find(fa[p])); }
void merge(ll p, ll q) {
p = find(p);
q = find(q);
fa[p] = q;
}
vector<pair<ll, ll> > g[N];
ll h[505][505], vis[505];
void dfs(ll from, ll p) {
vis[p] = 1;
for (ll i = 0; i < g[p].size(); i++) {
ll q = g[p][i].first;
if (vis[q])
continue;
h[from][q] = max(h[from][p], g[p][i].second);
dfs(from, q);
}
}
int main() {
ios::sync_with_stdio(false);
cin >> n >> m;
for (ll i = 1; i <= m; i++) {
ll u, v, w;
cin >> u >> v >> w;
e[i].u = u;
e[i].v = v;
e[i].w = w;
}
sort(e + 1, e + m + 1);
for (ll i = 1; i <= n; i++) fa[i] = i;
for (ll i = 1; i <= m; i++) {
ll p = find(e[i].u), q = find(e[i].v);
if (p != q) {
merge(p, q);
ans += e[i].w;
g[e[i].u].push_back(make_pair(e[i].v, e[i].w));
g[e[i].v].push_back(make_pair(e[i].u, e[i].w));
}
}
for (ll i = 1; i <= n; i++) {
memset(vis, 0, sizeof vis);
dfs(i, i);
}
ll delta = 1e+9;
for (ll i = 1; i <= m; i++)
if (e[i].w - h[e[i].u][e[i].v] > 0) {
delta = min(delta, e[i].w - h[e[i].u][e[i].v]);
}
cout << ans + delta << endl;
}
10069. 「一本通 3.1 练习 4」Tree
显然具有可二分性
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll n, m, k, fa[100005];
double ans;
ll find(ll p) { return p == fa[p] ? p : (fa[p] = find(fa[p])); }
void merge(ll p, ll q) {
p = find(p);
q = find(q);
if (p > q)
swap(p, q);
fa[q] = p;
}
struct Edge {
ll u, v, c;
double w;
bool operator<(const Edge &b) { return w < b.w; }
} e[100005];
int mst() {
ans = 0;
int cnt = 0;
sort(e + 1, e + m + 1);
for (ll i = 1; i <= n; i++) fa[i] = i;
for (ll i = 1; i <= m; i++) {
if (find(e[i].u) == find(e[i].v))
continue;
ans += e[i].w;
cnt += e[i].c;
merge(e[i].u, e[i].v);
}
return cnt;
}
int s[100005], t[100005], c[100005], col[100005];
int main() {
ios::sync_with_stdio(false);
cin >> n >> m >> k;
for (int i = 1; i <= m; i++) cin >> s[i] >> t[i] >> c[i] >> col[i], ++s[i], ++t[i];
double l = -1000, r = 1000;
int cnt;
while (r - l > 1e-6) {
double mid = (l + r) / 2.0;
for (int i = 1; i <= m; i++)
e[i].u = s[i], e[i].v = t[i], e[i].c = col[i], e[i].w = c[i] + (double)(col[i]) * mid;
if (mst() > n - k - 1)
l = mid;
else
r = mid;
}
cout << (int)(ans - l * (n - k - 1) + 0.01) << endl;
}