kuangbin专题六:最小生成树
不知不觉已经刷到专题六了,但感觉进度还是有点慢了(*  ̄︿ ̄)
思路:模板题。
#include <iostream> #include <algorithm> #include <stdio.h> using namespace std; const int maxn = 505; int p[maxn]; int n; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py){ p[px] = py; } } int idx; struct Edge{ int u, v, w; } e[maxn]; bool cmp(const Edge& a, const Edge& b){ return a.w < b.w; } void init(){ for(int i = 0; i <= n; i++) p[i] = i; idx = 0; } int main(){ while(cin >> n && n){ init(); for(int i = 1; i < n; i++){ char u, v; int k, w; cin >> u >> k; for(int j = 1; j <= k; j++){ cin >> v >> w; e[idx++] = {u - 'A', v - 'A', w}; } } sort(e, e + idx, cmp); int res = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; int pu = findP(u), pv = findP(v); if(pu != pv){ res += w; Union(u, v); } } cout << res << endl; } return 0; }
思路:模板题。
#include <iostream> #include <algorithm> #include <stdio.h> using namespace std; const int maxn = 1e5; int p[maxn]; int n, m; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py){ p[px] = py; } } struct Edge{ int u, v, w; } e[maxn]; bool cmp(const Edge& a, const Edge& b){ return a.w < b.w; } void init(){ for(int i = 0; i <= n; i++) p[i] = i; } int main(){ while(cin >> n && n){ init(); cin >> m; for(int i = 0; i < m; i++){ cin >> e[i].u >> e[i].v >> e[i].w; } sort(e, e + m, cmp); int res = 0; for(int i = 0; i < m; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; int pu = findP(u), pv = findP(v); if(pu != pv){ Union(pu, pv); res += w; } } cout << res << endl; } return 0; }
POJ2031 Building a Space Station
思路:先连相交的cell,再找最小生成树。
#include <iostream> #include <algorithm> #include <stdio.h> #include <cmath> using namespace std; const int maxn = 1e4 + 5; int p[maxn]; int n; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Cell{ double x, y, z, r; } cell[105]; double dis(Cell &a, Cell &b){ double dx = a.x - b.x, dy = a.y - b.y, dz = a.z - b.z; return sqrt(dx * dx + dy * dy + dz * dz); } int idx; struct Edge{ int u, v; double w; } e[maxn]; bool cmp(const Edge& a, const Edge& b){ return a.w < b.w; } void init(){ idx = 0; for(int i = 0; i <= n; i++) p[i] = i; } int main(){ while(cin >> n && n){ init(); for(int i = 1; i <= n; i++) cin >> cell[i].x >> cell[i].y >> cell[i].z >> cell[i].r; // check distance between cells for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++){ double d = dis(cell[i], cell[j]); if(d < cell[i].r + cell[j].r) Union(i, j); else{ e[idx].u = i; e[idx].v = j; e[idx].w = d - cell[i].r - cell[j].r; idx++; } } sort(e, e + idx, cmp); double res = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v; double w = e[i].w; int pu = findP(u), pv = findP(v); if(pu != pv){ Union(u, v); res += w; } } printf("%.3f\n", res); } return 0; }
思路:模板题。
#include <iostream> #include <algorithm> #include <stdio.h> #include <cmath> using namespace std; const int maxn = 1e4 + 5; int p[maxn]; int n, q; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } int idx; struct Edge{ int u, v, w; } e[maxn]; bool cmp(const Edge& a, const Edge& b){ return a.w < b.w; } void init(){ idx = 0; for(int i = 0; i <= n; i++) p[i] = i; } int main(){ cin >> n; init(); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){ int d; cin >> d; if(i < j){ e[idx].u = i, e[idx].v = j; e[idx].w = d; idx++; } } sort(e, e + idx, cmp); cin >> q; for(int i = 1; i <= q; i++){ int u, v; cin >> u >> v; Union(u, v); } int res = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; int pu = findP(u), pv = findP(v); if(pu != pv){ Union(u, v); res += w; } } cout << res << endl; return 0; }
思路:模板题。
思路:模板题。
#include<iostream> #include<algorithm> using namespace std; const int maxn = 2004; char code[maxn][8]; int p[maxn]; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } int idx = 0; struct Edge{ int u, v, w; } e[maxn * maxn / 2]; bool cmp(const Edge &x, const Edge &y){ return x.w < y.w; } int dis(int x, int y){ int d = 0; for(int i = 0; i < 7; i++) if(code[x][i] != code[y][i]) d++; return d; } int main(){ int N; while(cin >> N && N){ // initialization for(int i = 0; i <= N; i++) p[i] = i; idx = 0; // read code and construct graph for(int i = 1; i <= N; i++) cin >> code[i]; for(int i = 1; i <= N; i++) for(int j = i + 1; j <= N; j++){ e[idx].u = i, e[idx].v = j; e[idx].w = dis(i, j); idx++; } sort(e, e + idx, cmp); // shortest path int res = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; int pu = findP(u), pv = findP(v); if(pu != pv){ res += w; Union(u, v); } } cout << "The highest possible quality is 1/" << res << "." << endl; } return 0; }
思路:选出最小生成树,去掉权值最大的几个结点。一直莫名WA让人不爽。抄了以前不知道在哪抄的代码。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int maxn = 505; int p[maxn]; int S, P, idx; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v; double w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } struct Pos{ int x, y; } pos[maxn]; double solve(){ double ans = 0; int groupN = P; for(int i = 0; i < idx; i++){ if(groupN <= S) break; int u = e[i].u, v = e[i].v; double w = e[i].w; if(findP(u) == findP(v)) continue; Union(u, v); ans = w; groupN--; } return ans; } int main(){ int T; cin >> T; while(T--){ cin >> S >> P; for(int i = 0; i <= P; i++) p[i] = i; // read site for(int i = 0; i < P; i++) cin >> pos[i].x >> pos[i].y; idx = 0; // connect each site for(int i = 0; i < P; i++) for(int j = i + 1; j < P; j++){ int dx = pos[i].x - pos[j].x, dy = pos[i].y - pos[j].y; e[idx].u = i, e[idx].v = j; e[idx++].w = sqrt(dx * dx + dy * dy); } sort(e, e + idx, cmp); printf("%.2f\n", solve()); } return 0; }
思路:模板题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int maxn = 755; int p[maxn]; int S, P, idx; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v; double w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } struct Pos{ int x, y; } pos[maxn]; int main(){ int n, m; // read data cin >> n; for(int i = 0; i <= n; i++) p[i] = i; for(int i = 1; i <= n; i++) cin >> pos[i].x >> pos[i].y; cin >> m; for(int i = 1; i <= m; i++){ int u, v; cin >> u >> v; Union(u, v); } // construct edge int idx = 0; for(int i = 1; i <= n; i++) for(int j = i + 1; j <= n; j++){ int dx = pos[i].x - pos[j].x, dy = pos[i].y - pos[j].y; e[idx].u = i, e[idx].v = j; e[idx++].w = sqrt(dx * dx + dy * dy); } sort(e, e + idx, cmp); for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v; if(findP(u) != findP(v)){ Union(u, v); cout << u << " " << v << endl; } } return 0; }
思路:模板题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const int maxn = 105; int p[maxn]; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v, w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } int main(){ int n; while(cin >> n){ for(int i = 0; i <= n; i++) p[i] = i; int idx = 0; for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++){ int x; cin >> x; if(i < j){ e[idx].u = i, e[idx].v = j; e[idx++].w = x; } } sort(e, e + idx, cmp); int ans = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v; if(findP(u) != findP(v)){ Union(u, v); ans += e[i].w; } } cout << ans << endl; } return 0; }
思路:先建图,再模板。这题以前我弟出给我做过,当时居然不会,丢人了。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<queue> #include<vector> using namespace std; const int maxn = 55 * 55; const int maxm = 55; int p[maxn]; char maze[maxm][maxm]; int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1}; int x, y; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v, w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } struct Pos{ int x, y; }; int dis[maxm][maxm]; void bfs(int r, int c){ memset(dis, 0x3f, sizeof(dis)); dis[r][c] = 0; queue<Pos> q; Pos pos = {r, c}; q.push(pos); while(q.size()){ Pos p = q.front(); q.pop(); int px = p.x, py = p.y; for(int i = 0; i < 4; i++){ int nx = px + dx[i], ny = py + dy[i]; if(nx < 1 || nx > y || ny < 1 || ny > x) continue; if(maze[nx][ny] != '#' && dis[nx][ny] == 0x3f3f3f3f){ Pos np = {nx, ny}; q.push(np); dis[nx][ny] = dis[px][py] + 1; } } } } int main(){ int T; cin >> T; while(T--){ cin >> x >> y; for(int i = 0; i <= x * y; i++) p[i] = i; vector<Pos> v; // read maze char line[maxm]; fgets(line, maxm, stdin); for(int i = 1; i <= y; i++){ fgets(line, maxm, stdin); for(int j = 1; j <= x; j++){ maze[i][j] = line[j-1]; if(maze[i][j] == 'S' || maze[i][j] == 'A'){ Pos p = {i, j}; v.push_back(p); } } } int idx = 0; // build connection by bfs for(int i = 0; i < v.size(); i++){ bfs(v[i].x, v[i].y); for(int j = 0; j < v.size(); j++){ if(i == j) continue; e[idx].u = i, e[idx].v = j; e[idx++].w = dis[v[j].x][v[j].y]; } } sort(e, e + idx, cmp); int ans = 0; // get output for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; if(findP(u) != findP(v)){ Union(u, v); ans += w; } } cout << ans << endl; } return 0; }
思路:次小生成树。
思路:模板题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 105; int p[maxn]; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v, w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } int main(){ int N; while(scanf("%d", &N) && N){ for(int i = 0; i <= N; i++) p[i] = i; int idx = 0; for(int i = 1; i <= N * (N - 1) / 2; i++){ scanf("%d%d%d", &e[idx].u, &e[idx].v, &e[idx].w); idx++; } sort(e, e + idx, cmp); int ans = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; if(findP(u) != findP(v)){ Union(u, v); ans += w; } } printf("%d\n", ans); } return 0; }
思路:模板题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 105; int p[maxn]; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v, w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } int main(){ int N; while(cin >> N && N){ for(int i = 0; i <= N; i++) p[i] = i; int idx = 0; for(int i = 1; i < N; i++){ char u; int k; cin >> u >> k; while(k--){ char v; int w; cin >> v >> w; e[idx].u = u - 'A'; e[idx].v = v - 'A'; e[idx].w = w; idx++; } } sort(e, e + idx, cmp); int ans = 0; for(int i = 0; i < idx; i++){ int u = e[i].u, v = e[i].v, w = e[i].w; if(findP(u) != findP(v)){ Union(u, v); ans += w; } } printf("%d\n", ans); } return 0; }
思路:模板题。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn = 105; int p[maxn]; int findP(int x){ return x == p[x] ? p[x] : p[x] = findP(p[x]); } void Union(int x, int y){ int px = findP(x), py = findP(y); if(px != py) p[px] = py; } struct Edge{ int u, v; double w; }e[maxn * maxn]; bool cmp(const Edge& x, const Edge& y){ return x.w < y.w; } struct Pos{ int x, y; } pos[maxn]; double dis(Pos &a, Pos &b){ int dx = a.x - b.x, dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } int main(){ int T; cin >> T; while (T--){ int C; cin >> C; for(int i = 0; i <= C; i++) p[i] = i; for(int i = 1; i <= C; i++) cin >> pos[i].x >> pos[i].y; int idx = 0; for(int i = 1; i <= C; i++) for(int j = i + 1; j <= C; j++){ double d = dis(pos[i], pos[j]); if(d >= 10 && d <= 1000){ e[idx].u = i, e[idx].v = j; e[idx++].w = d; } } sort(e, e + idx, cmp); double ans = 0; for(int i = 0; i < idx; i++){ if(findP(e[i].u) != findP(e[i].v)){ Union(e[i].u, e[i].v); ans += e[i].w; } } bool reachAll = true; for(int i = 1; i <= C; i++) if(findP(1) != findP(i)) reachAll = false; if(reachAll) printf("%.1f\n", ans * 100); else printf("oh!\n"); } return 0; }

浙公网安备 33010602011771号