边权最大值最小问题
对于边权最大值最小的问题
思路非常简单:
首先是排序后跑最小生成树(Kruskal)
每一次循环都判断一下起点和终点是否联通了
如果联通了,输出当前边的边权即可。
思想解释就是:
我们首先保证了边权是单调递增的,如果在某一个时刻,将两个联通块进行了合并,使得起点和终点能够联通,而在前一个时刻不能
我们想,此后我们可能合并更多的联通块,可能有更多的生成树,但是因为边权是递增的
所以此后生成树的最大边的边权肯定比当前生成树的最大边的边权小,所以当前边的边权就是起点到终点的边权最大值最小的情况
如果是1—n,实际上就是一颗最小生成树的最大边
1 #include<bits/stdc++.h> 2 #define uint unsigned int 3 using namespace std; 4 const int maxn = 100086; 5 const int maxm = 600086; 6 struct shiki { 7 int x, y, val; 8 }e[maxm]; 9 int n, m, s, t; 10 int fa[maxn]; 11 12 inline int read() { 13 int x = 0, y = 1; 14 char ch = getchar(); 15 while(!isdigit(ch)) { 16 if(ch == '-') y = -1; 17 ch = getchar(); 18 } 19 while(isdigit(ch)) { 20 x = (x << 1) + (x << 3) + ch - '0'; 21 ch = getchar(); 22 } 23 return x * y; 24 } 25 26 inline bool cmp(shiki a, shiki b) { 27 return a.val < b.val;} 28 29 int getfather(int x) { 30 if(x == fa[x]) return x; 31 return fa[x] = getfather(fa[x]); 32 } 33 34 int main() { 35 n = read(), m = read(), s = read(), t = read(); 36 for(register uint i = 1; i <= m; ++i) 37 e[i].x = read(), e[i].y = read(), e[i].val = read(); 38 sort(e + 1, e + m + 1, cmp); 39 for(register uint i = 1; i <= n; ++i) fa[i] = i; 40 for(register uint i = 1; i <= m; ++i) { 41 int u = getfather(e[i].x); 42 int v = getfather(e[i].y); 43 if(u != v) fa[u] = v; 44 if(getfather(s) == getfather(t)) { 45 cout << e[i].val << '\n'; 46 return 0; 47 } 48 } 49 return 0; 50 }