题目链接: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; }
原文地址:http://blog.csdn.net/lsgqjh/article/details/46241803