题意就是给你一张无向连通图,试问对于图上所有点对(u,v)从u到v的所有路径中边权最大值的最小值的最大值。
定义f(u,v)表示从u到v所有路径中边权最大值的最小值,对所有点对取其最大。
实际上就是求图G的最小生成树的最大边权。
考虑kruskal算法流程,每次选取边权最小的且不产生圈的边加入mst。
至算法结束,图恰好连通,并且选取的边权都是最小的。
对于那些产生回路的边加入到mst中是没有意义的,因为之前保持图连通时选取的边权更小。
注意考虑重边。
http://poj.org/problem?id=2395
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <map> 5 #include <queue> 6 using namespace std; 7 typedef __int64 LL; 8 const int maxn = 2e3 + 10; 9 const int maxm = 1e4 + 10; 10 const int inf = 1e9 + 1e8; 11 struct Edge{ 12 int from, to, next, c; 13 bool operator < (const Edge& rhs) const{ 14 return c < rhs.c; 15 } 16 }edge[maxm << 1]; 17 struct Point{ 18 int x, y, c; 19 bool operator < (const Point& rhs) const{ 20 return x < rhs.x || (x == rhs.x && y < rhs.y) || (x == rhs.x && y == rhs.y && c < rhs.c); 21 } 22 }; 23 int head[maxn], N; 24 Point a[maxm]; 25 int n, m, k; 26 int ans; 27 bool vis[maxn]; 28 29 void addEdge(int u, int v, int c){ 30 edge[N].next = head[u]; 31 edge[N].from = u; 32 edge[N].to = v; 33 edge[N].c = c; 34 head[u] = N++; 35 } 36 37 int fa[maxn]; 38 39 int find(int u){ 40 if(fa[u] == -1 || fa[u] == u) return u; 41 return fa[u] = find(fa[u]); 42 } 43 int main(){ 44 //freopen("in.txt", "r", stdin); 45 while(~scanf("%d%d", &n, &m)){ 46 N = 0; 47 memset(head, -1, sizeof head); 48 for(int i = 0; i < m; i++){ 49 scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].c); 50 if(a[i].x > a[i].y) swap(a[i].x, a[i].y); 51 } 52 sort(a, a + m); 53 k = 0; 54 for(int i = 0; i < m; i++){ 55 a[k++] = a[i]; 56 while(i < m - 1 && a[i].x == a[i + 1].x && a[i].y == a[i + 1].y) ++i; 57 } 58 for(int i = 0; i < k; i++) addEdge(a[i].x, a[i].y, a[i].c); 59 sort(edge, edge + N); 60 int ans = -1; 61 memset(fa, -1, sizeof fa); 62 for(int i = 0; i < N; i++){ 63 int u = edge[i].from, v = edge[i].to; 64 int fu = find(u), fv = find(v); 65 if(fu != fv) fa[fv] = fu, ans = max(ans, edge[i].c); 66 } 67 printf("%d\n", ans); 68 } 69 return 0; 70 }
时间: 2024-11-05 13:36:46