这道题显然是一道最小生成树的问题,参考算法导论中的Kruskal方法,先对路径长度进行排序,然后使用并查集(Disjoint Set Union)来判断节点是否连通,记录连接所有节点的最后一条路径的长度即为最大的长度了。
下面的并查集算法还可以通过设置rank数组记录节点的等级来进一步优化。总的来说还是一道简单题。
#include <cstdio> #include <algorithm> using namespace std; struct Edge{ int x, y; int dis; }; int pre[501]; int find(int x) { int r = x; while (pre[r] != r){ r = pre[r]; } int i = x, j; while (i != r){ j = pre[i]; pre[i] = r; i = j; } return r; } bool joint(int x, int y) { int xRoot = find(x), yRoot = find(y); if (xRoot == yRoot) return false; pre[xRoot] = yRoot; return true; } bool cmp(Edge e1, Edge e2) { return e1.dis < e2.dis; } int main() { int t; scanf("%d", &t); while (t--){ int n; Edge edge[25001]; scanf("%d", &n); for (int i = 0; i < n; i++){ pre[i] = i; } int cnt = 0; for (int i = 0; i < n; i++){ for (int j = 0; j < n; j++){ int dis; scanf("%d", &dis); if (i > j)continue; edge[cnt].x = i; edge[cnt].y = j; edge[cnt++].dis = dis; } } sort(edge, edge + cnt, cmp); int max = -1; for (int i = 0; i < cnt; i++){ if (joint(edge[i].x, edge[i].y)){ max = edge[i].dis > max ? edge[i].dis : max; } } printf("%d\n", max); } return 0; }
时间: 2024-10-22 08:31:27