Kuskal/Prim POJ 1789 Truck History
题意:给出n个长度为7的字符串,一个字符串到另一个的距离为不同的字符数,问所有连通的最小代价是多少
分析:Kuskal/Prim: 先用并查集做,简单好写,然而效率并不高,稠密图应该用Prim而且要用邻接矩阵,邻接表的效率也不高。裸题但题目有点坑爹:(
Kruskal:
#include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const int MAXN = 2e3 + 10; const int INF = 0x3f3f3f3f; struct UF { int rt[MAXN], rk[MAXN]; void init(void) { memset (rt, -1, sizeof (rt)); memset (rk, 0, sizeof (rk)); } int Find(int x) { return (rt[x] == -1) ? x : rt[x] = Find (rt[x]); } void Union(int x, int y) { x = Find (x), y = Find (y); if (x == y) return ; if (rk[x] > rk[y]) { rt[y] = x; rk[x] += rk[y] + 1; } else { rt[x] = y; rk[y] += rk[x] + 1; } } bool same(int x, int y) { return Find (x) == Find (y); } }uf; char s[MAXN][10]; struct Node { int u, v, w; }node[MAXN*MAXN/2]; int n, tot; bool cmp(Node x, Node y) {return x.w < y.w;} void get_w(int x) { for (int i=1; i<x; ++i) { int res = 0; for (int j=0; j<7; ++j) { if (s[i][j] != s[x][j]) res++; } node[++tot].u = i; node[tot].v = x; node[tot].w = res; } } int main(void) //POJ 1789 Truck History { // freopen ("POJ_1789.in", "r", stdin); while (scanf ("%d", &n) == 1) { if (n == 0) break; tot = 0; for (int i=1; i<=n; ++i) { scanf ("%s", s[i]); get_w (i); } sort (node+1, node+1+tot, cmp); int ans = 0; uf.init (); for (int i=1; i<=tot; ++i) { int u = node[i].u; int v = node[i].v; int w = node[i].w; if (!uf.same (u, v)) {uf.Union (u, v); ans += w;} } printf ("The highest possible quality is 1/%d.\n", ans); } return 0; }
Prim:
/* 模版搞错了,纠结半天。。。算法还是想清楚才行啊 */ #include <cstdio> #include <algorithm> #include <cstring> #include <string> #include <iostream> #include <vector> #include <queue> using namespace std; const int MAXN = 2e3 + 10; const int INF = 0x3f3f3f3f; int d[MAXN], w[MAXN][MAXN]; bool vis[MAXN]; int n; char s[MAXN][10]; int Prim(int s) { memset (vis, false, sizeof (vis)); memset (d, INF, sizeof (d)); d[s] = 0; int ret = 0; for (int i=1; i<=n; ++i) { int mn = INF, u = -1; for (int i=1; i<=n; ++i) { if (!vis[i] && d[i] < mn) mn = d[u=i]; } if (u == -1) return -1; vis[u] = true; ret += d[u]; for (int i=1; i<=n; ++i) { if (!vis[i] && d[i] > w[u][i]) { d[i] = w[u][i]; } } } return ret; } void get_w(int x) { for (int i=1; i<x; ++i) { int res = 0; for (int j=0; j<7; ++j) { if (s[i][j] != s[x][j]) res++; } w[i][x] = w[x][i] = res; } } int main(void) { while (scanf ("%d", &n) == 1) { if (n == 0) break; memset (w, INF, sizeof (w)); for (int i=1; i<=n; ++i) { scanf ("%s", s[i]); get_w (i); } printf ("The highest possible quality is 1/%d.\n", Prim (1)); } return 0; }
编译人生,运行世界!