Description
牛们的饲料吃完了,这是一个必须马上解决的严重问题。 Bessie想去其他农场看看他们的饲料情况。总共有N (2 <= N <= 2,000)个农场,编号1到N,Bessie打算到每个农场去看看。Bessie从编号1的农场出发,她将穿过部分或者是全部的M条双向道路,这些道路把所有农场连接了起来,并且每条路的长度不超过1,000,000,000米。有的农场间可能有多条不同长度的道路相连。从1号农场出发可以到达所有其他农场。
Bessie想知道她需要携带多大的水壶。她每走1米的路,她就会喝掉1升的水。因为她在每个农场都可以把水壶灌满,所以她只需要考虑其中最长的一条道路。因此,她想事先设计出一条路径,使她能够达到所有的农场,并且使她携带的水尽可能少。请你帮Bessie算出她最少需要携带多大的水壶。
Input
第一行,两个整数N和M(M<=10000)
接下来M行,每行三个整数X,Y,Z,表示农场X与农场Y之间有条长度为Z的道路
Output
一个整数,表示Bessie携带的水壶最少要能装多少升水。
Sample Input
3 3
1 2 23
2 3 1000
1 3 43
Sample Output
43
【分析】
算法:最小生成树
最小生成树的算法通常是Prim或Kruskal,而Kruskal有个很好的性质,就是求出来的生成树最长的那条边是最短的。这个性质显然成立,因为Kruskal是基于贪心算法的。
那么再看看这道题,就变成了裸的Kruskal。
【代码】
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<iostream> #include<algorithm> #include<queue> using namespace std; struct node{ int x,y,z; }edge[10005]; int N,M,father[2005]; void _in(int &x) { char t; t=getchar(); while(t<'0'||'9'<t) t=getchar(); for(x=t-'0',t=getchar();'0'<=t&&t<='9';x=x*10+t-'0',t=getchar()); } int _getfather(int x) { if(x!=father[x]) father[x]=_getfather(father[x]); return father[x]; } void _qst_edge(int l,int r) { int i=l,j=r,mz=edge[(i+r)>>1].z; while(i<=j) { while(edge[i].z<mz) i++; while(edge[j].z>mz) j--; if(i<=j) { swap(edge[i],edge[j]); i++;j--; } } if(l<j) _qst_edge(l,j); if(i<r) _qst_edge(i,r); } void _kruskal() { int fx,fy,cnt,k,ans; cnt=k=ans=0; while(cnt<N-1) { k++; fx=_getfather(edge[k].x); fy=_getfather(edge[k].y); if(fx!=fy) { father[fx]=fy; ans=max(ans,edge[k].z); cnt++; } } printf("%d\n",ans); } void _init() { _in(N);_in(M); for(int i=1;i<=M;i++) { _in(edge[i].x); _in(edge[i].y); _in(edge[i].z); } _qst_edge(1,M); for(int i=1;i<=N;i++) father[i]=i; } void _solve() { _kruskal(); } int main() { _init(); _solve(); return 0; }