题目链接:http://poj.org/problem?id=1861
和前面的题目极其类似,比较有意思的是这里有点儿坑人的地方,但是我并没有注意,歪打正着。幸亏样例没有仔细看。题目这次只要求在保证链接所有顶点的情况下,求出最长的那条边。并没有要求路径总权值最小。所以可以任意添加某条小于最长的那个边权值的其它 可添加边,尽管他可能成环。所有才有了奇葩的样例。其实完全是构造最小生成树的思路。
#include<iostream>
#include<algorithm>
#include<string.h>
#include<stack>
#include<queue>
using namespace std;
const int M=10046;
int F[M];
int r[M];
int N,m;
int res,num;
struct Edge
{
int u,v,w;
} per[15005];
bool cmp(Edge a, Edge b)
{
return a.w<b.w;
}
void init()
{
for(int i=1; i<=N; i++)
{
r[i]=1;
F[i]=i;
}
}
//int Find(int x)
//{
// if(x!=F[x])
// return F[x]=Find(F[x]);
//}
int Find(int x)
{
int r=x;
while(r!=F[r])
{
r=F[r];
}
int k=x;
while(k!=r)
{
int t=F[k];
F[k]=r;
k=t;
}
return r;
}
void union_set(int x,int y)
{
int tx=Find(x);
int ty=Find(y);
if(tx==ty)
return ;
else if(r[tx]>r[ty])
F[ty]=tx;
else if(r[tx]<r[ty])
F[tx]=ty;
else
{
F[tx]=ty;
r[ty]++;
}
}
void kru()
{
//stack<int>cnt;
queue<int>cnt;
res=-1;
for(int i=0; i<m; i++)
{
if(Find(per[i].u)!=Find(per[i].v))
{
num++;
if(res<per[i].w)
res=per[i].w;
union_set(per[i].u,per[i].v);
cnt.push(i);
}
if(num==N-1)
{
cout<<res<<endl<<cnt.size()<<endl;
while(!cnt.empty())
{
int t=cnt.front();
cnt.pop();
cout<<per[t].u<<" "<<per[t].v<<endl;
}
break;
}
}
}
int main()
{
while(cin>>N>>m)
{
num=0;
init();
for(int i=0; i<m; i++)
{
cin>>per[i].u>>per[i].v>>per[i].w;
}
sort(per,per+m,cmp);
kru();
}
return 0;
}