====================================================================================
题目大意:公司要用网线把交换机都连起来,连成一个最小生成树,回答的时候第一行是最小生成树里边权最大的一条边,第二行是边数,后面是各条边连接的点对(虽然没要求排序我还是按左边的点升序排了下)。因为不是求边权和所以题目里说边权能到100w不足为虑。
解题思路:求最小生成树意思很明显了,给边是散边的形式,邻接表比较合适,也就是要用Kruskal。
p.s.:poj这道题的Sample Output是错的,当时看见吓得我一身冷汗以为审题有误,我这里改过来了。
//Memory: 864K Time: 110MS
#include
#include
#include
#include
using namespace std;
struct edge //用来存条件里的边集
{
edge( int A , int B , int V ):a(A),b(B),v(V){} //写好构造函数方便插入vector
int a , b , v;
bool operator < ( const edge &e )const //重载小于号方便sort排序
{
return v < e.v;
}
};
struct ansEdges //不带权值的边,用来存选中的边集
{
ansEdges(int A ,int B):a(A),b(B){} //写好构造函数方便插入vector
int a , b;
bool operator < ( const ansEdges &e )const //重载小于号方便sort排序
{
return a < e.a;
}
};
vector l;
vector ansL;
int father[1001] , ans , eN;
//并查集
int getFather(int x)
{
return (!father[x])?x:( father[x] = getFather(father[x]) );
}
void Union(int x , int y , int v)
{
int fx = getFather(x);
int fy = getFather(y);
if( fx == fy )
return;
father[fy] = fx;
if( v > ans ) //这里更新最大边权
ans = v;
ansL.push_back(ansEdges(x,y)); //加入选中的边集
eN++;
}
//Kruskal算法
void Kruskal(int n)
{
vector::iterator it;
for( it = l.begin() ; it != l.end() ; it++ )
{
if( eN == n-1 )
return;
Union(it->a,it->b,it->v);
}
}
int main()
{
int N , M;
scanf("%d%d", &N, &M);
while(M--)
{
int a , b , v;
scanf("%d%d%d", &a, &b, &v);
l.push_back(edge(a,b,v)); //加入条件边集
}
sort(l.begin(),l.end()); //条件边集升序排序
Kruskal(N);
sort(ansL.begin(),ansL.end()); //选中边集升序排序
printf("%d\n%d\n", ans, ansL.size());
vector::iterator it;
for( it = ansL.begin() ; it != ansL.end() ; it++ )
printf("%d %d\n", it->a, it->b);
return 0;
}
难得oj言而有信真只有一组数据。