最小生成树开搞!
1140. 最短网络 - AcWing题库
p r i m prim prim 模板题,因为数据量小,而且是以邻接矩阵的方式给出图,所以用 p r i m prim prim 算法更加方便
#includeusing namespace std; const int N = 110; int w[N][N]; int dist[N]; bool st[N]; int n; int prim() { memset(dist, 0x3f, sizeof dist); dist[1] = 0; int res = 0; for (int i = 0; i < n; i++) { int t = -1; for (int j = 1; j <= n; j++) // 找到距离生成树最近的点 if (!st[j] && (t == -1 || dist[t] > dist[j])) t = j; res += dist[t]; // 把这个点加入生成树 st[t] = true; for (int j = 1; j <= n; j++) // 用这个点更新其他点 dist[j] = min(dist[j], w[t][j]); } return res; } int main(void) { cin >> n; for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) cin >> w[i][j]; cout << prim() << endl ; return 0; }
1141. 局域网 - AcWing题库
K r u s k a l Kruskal Kruskal 模板题,如果已经在一个集合的边就删掉
#includeusing namespace std; const int N = 110, M = 210; int n, m; struct Edge { int a, b, w; bool operator< (const Edge &t) const // 重载运算符 { return w < t.w; } }e[M]; int p[N]; int find(int x) // 并查集模板 { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main(void) { cin >> n >> m; for (int i = 1; i <= n; i++) p[i] = i; for (int i = 0; i < m; i++) { int a, b, w; cin >> a >> b >> w; e[i] = {a, b, w}; } sort(e, e + m); // 把边从小到大排序 int res = 0; for (int i = 0; i < m; i++) { int a = find(e[i].a), b = find(e[i].b), w = e[i].w; if (a != b) p[a] = b; // 如果他们两个不在一个集合中,那就加到一起 else res += w; // 如果是,那就把这条边删掉 } cout << res << endl ; return 0; }
1142. 繁忙的都市 - AcWing题库
K r u s k a l Kruskal Kruskal 模板题,找最小生成树的最长边即可
#includeusing namespace std; const int N = 310, M = 8010; int n, m; struct Edge { int a, b, w; bool operator< (const Edge &t) const { return w < t.w; } }e[M]; int p[N]; int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } int main(void) { cin >> n >> m; for (int i = 1; i <= n; i++) p[i] = i; for (int i = 0; i < m; i++) { int a, b, w; cin >> a >> b >> w; e[i] = {a, b, w}; } sort(e, e + m); int res = 0; for (int i = 0; i < m; i++) { int a = find(e[i].a), b = find(e[i].b), w = e[i].w; if (a != b) { p[a] = b; res = max(res, w); } } cout << n - 1 << " " << res << endl ; return 0; }
1143. 联络员 - AcWing题库
还是 K r u s k a l Kruskal Kruskal 模板题,根据题意套模板就行
#includeusing namespace std; const int N = 2010, M = 10010; int n, m, cnt, res; int P[N]; struct Edge { int a, b, w; bool operator< (const Edge &t) const { return w < t.w; } }e[M]; int find(int x) { if (x != P[x]) P[x] = find(P[x]); return P[x]; } int main(void) { cin >> n >> m; for (int i = 1; i <= n; i++) P[i] = i; for (int i = 0; i < m; i++) { int p, a, b, w; cin >> p >> a >> b >> w; if (p == 1) { res += w; a = find(a), b = find(b); if (a != b) P[a] = b; } else { e[cnt++] = {a, b, w}; } } sort(e, e + cnt); for (int i = 0; i < cnt; i++) { int a = find(e[i].a), b = find(e[i].b), w = e[i].w; if (a != b) { P[a] = b; res += w; } } cout << res << endl ; return 0; }
1146. 新的开始 - AcWing题库
这题给了邻接矩阵,应该是用 p r i m prim prim 算法,但是我顺手写的是 K r u s k a l Kruskal Kruskal 算法,做法也很简单,设一个超级源点,然后让这个源点向每一个发电机连建边,然后跑一边模板即可。
#includeusing namespace std; const int N = 310, M = 100010; int n, p[N], cnt, x; struct Edge { int a, b, w; bool operator< (const Edge &t) const { return w < t.w; } }e[M + N]; int find(int x) { if (x != p[x]) p[x] = find(p[x]); return p[x]; } int main(void) { ios::sync_with_stdio(false); cin.tie(0); cin >> n; for (int i = 0; i <= n; i++) p[i] = i; for (int i = 1; i <= n; i++) { cin >> x; e[cnt++] = {0, i, x}; } for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { cin >> x; e[cnt++] = {i, j, x}; } sort(e, e + cnt); int res = 0; for (int i = 0; i < cnt; i++) { int a = find(e[i].a), b = find(e[i].b), w = e[i].w; if (a != b) { res += w; p[a] = b; } } cout << res << endl ; return 0; }
1145. 北极通讯网络 - AcWing题库
现在给我弄得就只会写 K r u s k a l Kruskal Kruskal 算法了, K r u s k a l Kruskal Kruskal 真好用,每一次连边都是集合的合并,所以当集合不超过 k k k 个时就输出当前边即可
#include#define x first #define y second using namespace std; const int N = 510, M = N * N; typedef pair PII; PII v[N]; int n, m, p[N], cnt; struct Edge { int a, b; double w; bool operator< (const Edge &t) const { return w < t.w; } }e[M]; double get(PII a, PII b) { int dx = a.x - b.x, dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } int find(int x) { if (x != p[x]) p[x] = find(p[x]); return p[x]; } int main(void) { cin >> n >> m; for (int i = 1; i <= n; i++) p[i] = i; for (int i = 1; i <= n; i++) cin >> v[i].x >> v[i].y; for (int i = 1; i <= n; i++) for (int j = i + 1; j <= n; j++) e[cnt++] = {i, j, get(v[i], v[j])}; sort(e, e + cnt); for (int i = 0; i < cnt; i++) { int a = find(e[i].a), b = find(e[i].b); double w = e[i].w; if (a != b) { p[a] = b; if (-- n == m) { printf("%.2f", w); } } } return 0; }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)