poj3522Slim Span(暴力+Kruskal)
思路:
最小生成树是瓶颈生成树,瓶颈生成树满足最大边最小。
数据量较小,所以只需要通过Kruskal,将边按权值从小到大排序,枚举最小边求最小生成树,时间复杂度为O( nm(logm) )
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 100 + 5; const int inf = 0x3f3f3f3f; int n, m, pre[maxn]; struct edge{ int s, to, w; bool operator < ( const edge &a )const{ return w<a.w; } } ed[maxn*maxn]; inline int find( int x ){ return pre[x]==x ? x:find(pre[x]); } inline int kru(int s){ int res = -1, cnt = n; for( int i=1; i<=n; i++ ) pre[i] = i; for( int i=s; i<m; i++ ){ int fx = find(ed[i].s); int fy = find(ed[i].to); if( fx!=fy ){ pre[fx] = fy; cnt --; if( cnt==1 ){ //每遍历一条边就少一个点,除第一次外把s点和该边连接的另一边加入,全部;联通时cnt==1而不是cnt==0 res = ed[i].w; break; } } } return res-ed[s].w; //不连通时 res==-1 返回值一定小于0 } int main(){ // freopen("in.txt", "r", stdin); while( ~scanf("%d%d", &n, &m) && (n||m) ){ for( int i=0; i<m; i++ ) scanf("%d%d%d", &ed[i].s, &ed[i].to, &ed[i].w); sort( ed, ed+m ); int ans = kru(0); //判断图联不联通 if( ans<0 ){ puts("-1"); continue; } for( int i=1; i<m; i++ ){ //枚举最小边,边的编号是从0开始 int tmp = kru(i); if( tmp<0 ) break; if( tmp<ans ) ans = tmp; } printf("%d\n", ans); } return 0; }