B
来源:互联网 发布:软件项目 文档 编辑:程序博客网 时间:2024/04/30 15:35
Think:
1知识点:并查集
2题意思考:将每一个单词视为一个结点,两点之间的权值即为联想背这两个单词的精力,这样背过n个单词即可认为将n个结点生成一棵树
3反思:初始化注意结点范围
vjudge题目链接
以下为Wrong Answer代码——初始化范围错误
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 1e3 + 2e4;const int M = 1040000;struct Edge{ int u; int v; int w;}edge[M];int tp, f[N];char st[N][14];bool cmp(struct Edge a, struct Edge b){ return a.w < b.w;}void Init(int n);int get_f(int v);bool Merge(int u, int v);int main(){ int n, m, w, i, j, k; while(~scanf("%d %d %d", &n, &m, &w)){ getchar(); tp = 0; for(i = 0; i < n; i++) scanf("%s", st[i]); for(i = 0; i < n; i++){ for(j = i+1; j < n; j++){ int cnt = 0; for(k = 0; k < m; k++){ if(st[i][k] != st[j][k]) cnt++; } int t; t = min(m, cnt*w); edge[tp].u = i, edge[tp].v = j, edge[tp].w = t; tp++; } } sort(edge, edge+tp, cmp); Init(n); int ans = 0, sum = 0; for(i = 0; i < tp; i++){ if(Merge(edge[i].u, edge[i].v)){ sum += edge[i].w; ans++; } if(ans == n-1) break; } sum += m; printf("%d\n", sum); } return 0;}void Init(int n){ for(int i = 1; i <= n; i++) f[i] = i;}int get_f(int v){ if(f[v] == v) return f[v]; f[v] = get_f(f[v]); return f[v];}bool Merge(int u, int v){ int t1 = get_f(u); int t2 = get_f(v); if(t1 == t2) return false; else { f[t2] = t1; return true; }}
以下为Accepted代码——Kruskal算法_156ms
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 1e3 + 2e4;const int M = 1040000;struct Edge{ int u; int v; int w;}edge[M];int tp, f[N];char st[N][14];bool cmp(struct Edge a, struct Edge b){ return a.w < b.w;}void Init(int n);int get_f(int v);bool Merge(int u, int v);int main(){ int n, m, w, i, j, k; while(~scanf("%d %d %d", &n, &m, &w)){ getchar(); tp = 0; for(i = 1; i <= n; i++) scanf("%s", st[i]); for(i = 1; i <= n; i++){ for(j = i+1; j <= n; j++){ int cnt = 0; for(k = 0; k < m; k++){ if(st[i][k] != st[j][k]) cnt++; } int t; t = min(m, cnt*w); edge[tp].u = i, edge[tp].v = j, edge[tp].w = t; tp++; } } sort(edge, edge+tp, cmp); Init(n); int ans = 0, sum = 0; for(i = 0; i < tp; i++){ if(Merge(edge[i].u, edge[i].v)){ sum += edge[i].w; ans++; } if(ans == n-1) break; } sum += m; printf("%d\n", sum); } return 0;}void Init(int n){ for(int i = 1; i <= n; i++) f[i] = i;}int get_f(int v){ if(f[v] == v) return f[v]; f[v] = get_f(f[v]); return f[v];}bool Merge(int u, int v){ int t1 = get_f(u); int t2 = get_f(v); if(t1 == t2) return false; else { f[t2] = t1; return true; }}
以下为Accepted代码——Prim算法_15ms
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int inf = 0x3f3f3f3f;const int N = 1e3 + 4e2;int vis[N], dis[N], e[N][N];char st[N][14];void Prim(int n, int m);int main(){ int n, m, w, i, j, k; while(~scanf("%d %d %d", &n, &m, &w)){ getchar(); for(i = 1; i <= n; i++) scanf("%s", st[i]); for(i = 1; i <= n; i++){ for(j = i; j <= n; j++){ if(i == j) e[i][j] = inf; else { int cnt = 0; for(k = 0; k < m; k++){ if(st[i][k] != st[j][k]) cnt++; } int t = min(m, cnt*w); e[i][j] = e[j][i] = t; } } } Prim(n, m); } return 0;}void Prim(int n, int m){ int i, num, miv, v, sum; memset(vis, 0, sizeof(vis)); for(i = 1; i <= n; i++) dis[i] = e[1][i]; vis[1] = 1, num = 1, sum = 0; while(num < n){ miv = inf; for(i = 1; i <= n; i++){ if(!vis[i] && miv > dis[i]){ miv = dis[i]; v = i; } } vis[v] = 1, sum += dis[v], num++; for(i = 1; i <= n; i++){ if(!vis[i] && dis[i] > e[v][i]) dis[i] = e[v][i]; } } printf("%d\n", sum+m);}