Prim小练习2
题目大意:
有n个农场,给出一个n*n的矩阵,第 i 行 j 列代表农场 i 到农场 j 的距离
求一个最小生成树连接所有农场,输出最小生成树中最大的边的边权值(由于本身最小生成树选取的边就满足了尽量使得使用的边的边权值小(从Kruskal的边的排序中明显看出))
很简单的最小生成树问题
两种算法做法如下:
Kruskal 算法:
Result : Accepted Memory : 500 KB Time : 235 ms
/* * Author: Gatevin * Created Time: 2014/7/16 21:45:23 * File Name: test.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; int T,V,E; int r[130000]; int f[510]; int u[130000]; int v[130000]; int w[130000]; bool cmp(const int& i, const int& j) { return w[i] < w[j]; } int get_father(int i) { if(i != f[i]) { f[i] = get_father(f[i]); } return f[i]; } int Kruskal() { for(int i = 1; i <= V; i++) f[i] = i; for(int i = 1; i <= E; i++) r[i] = i; int answer = 0; sort(r + 1, r + E + 1, cmp); for(int i = 1; i <= E; i++) { int e = r[i]; int rx = get_father(u[e]); int ry = get_father(v[e]); if(rx != ry) { answer = max(answer, w[e]); f[rx] = ry; } } return answer; } int main() { scanf("%d",&T); int tmp; while(T--) { scanf("%d",&V); E = 0; for(int i = 1; i <= V; i++) { for(int j = 1; j <= V; j++) { scanf("%d",&tmp); if(i > j) { E++; u[E] = i; v[E] = j; w[E] = tmp; r[E] = E; } } } int answer = Kruskal(); printf("%d\n",answer); } return 0; }
Result : Accepted Memory : 524 KB Time : 204 ms
/* * Author: Gatevin * Created Time: 2014/7/16 22:24:07 * File Name: test.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; int dis[510]; bool vis[510]; int T,V,tmp; const int inf = 0x7fffffff; vector <pair<int, int> > g[510]; int Prim() { memset(vis, 0, sizeof(vis)); fill(dis + 1, dis + V + 1, inf); dis[1] = 0; int ans = 0; for(int i = 1; i <= V; i++) { int mark = -1; for(int j = 1; j <= V; j++) { if(!vis[j]) { if(mark == -1) { mark = j; } else { if(dis[j] < dis[mark]) { mark = j; } } } } if(mark == -1) break; vis[mark] = -1; ans = max(ans, dis[mark]); for(int j = 0; j < g[mark].size(); j++) { if(!vis[g[mark][j].first]) { int x = g[mark][j].first; dis[x] = min(dis[x], g[mark][j].second); } } } return ans; } int main() { scanf("%d",&T); while(T--) { scanf("%d",&V); for(int i = 1; i <= V; i++) { for(int j = 1; j <= V; j++) { scanf("%d",&tmp); if(i > j) { g[i].push_back(make_pair(j, tmp)); g[j].push_back(make_pair(i, tmp)); } } } int answer = Prim(); printf("%d\n",answer); for(int i = 1; i <= V; i++) { if(!g[i].empty()) { g[i].clear(); } } } return 0; }