伤痕累累啊,WA了很多次,先是采用了并查集写法,但是Union操作写错了,贡献了几次WA,后来又采用了STL里面的replace代替并查集,但是replace又出现了误用。之后又看了discuss里面的帖子,还以为是测试数据本身的问题,最后是对照网上ac的代码才修正过来的。啥也不说了,直接贴上代码吧,望以后接受教训!
#include <iostream>
#include <algorithm>
#include <vector>
#include <utility>
#include <cstdio>
#include <cstdlib>
using namespace std;
bool Comp(pair<pair<int,int>,int> left, pair<pair<int,int>,int> right)
{
return left.second < right.second;
}
void MakeSet(vector<int>& p, vector<int>& r)
{
for(int i = 1; i < p.size(); ++i)
{
p[i] = i;
r[i] = 0;
}
}
int FindSet(vector<int>& p, int c)
{
if( p[c] != c )
{
p[c] = FindSet(p, p[c]);
}
return p[c];
}
void Union(vector<int>& p, vector<int>& r, int lc, int rc)
{
/*
* WA version
* p[rc] = FindSet(p, lc); // it is wrong, because p[rc]'s parent doesn't change, that is, the set which includes rc doesn't change all.
*/
int pl = FindSet(p, lc);
int pr = FindSet(p, rc);
if( r[pl] < r[pr] )
p[pl] = pr;
else
{
p[pr] = pl;
r[pl]==r[pr]?r[pl]++:NULL;
}
}
int main()
{
int n, m;
while( ~scanf("%d%d", &n, &m) )
{
vector<pair<pair<int,int>, int> > edges;
int u, v, w;
for(int i = 0; i < m; ++i)
{
scanf("%d%d%d", &u, &v, &w);
//cin >> u >> v >> w;
edges.push_back( make_pair(pair<int,int>(u, v), w) );
}
sort(edges.begin(), edges.end(), Comp);
vector<int> p, r;
p.resize( n + 1 );
r.resize( n + 1 );
/* **********another solution
*
int maxLen = 0;
for(int i = 0; i < edges.size(); ++i)
{
int u = edges[i].first.first;
int v = edges[i].first.second;
int w = edges[i].second;
if( p[u] != p[v] )
{
int oldValue = p[u], newValue = p[v];
replace(p.begin(), p.end(), oldValue, newValue); // replace(p.begin(), p.end(), p[u], p[v]) is wrong, causing me WA;
ans.push_back(pair<int,int>(u, v));
maxLen = w>maxLen?w:maxLen;
if( ans.size() == n-1 )
break;
}
}
cout << maxLen << endl;
cout << ans.size() << endl;
for(int i = 0; i < ans.size(); ++i)
cout << ans[i].first << ' ' << ans[i].second << endl;
*/
MakeSet( p , r );
vector<int> ans;
int maxLen = 0;
for(int i = 0; i < edges.size(); ++i)
{
int u = edges[i].first.first;
int v = edges[i].first.second;
int w = edges[i].second;
if( FindSet(p, u) != FindSet(p, v) )
{
Union(p, r, u, v);
ans.push_back( i );
maxLen = maxLen>w?maxLen:w;
if( ans.size() == n-1 )
break;
}
}
int size = ans.size();
cout << maxLen << endl;
cout << size << endl;
for(int i = 0; i < size; ++i)
{
printf("%d %d\n", edges[ans[i]].first.first, edges[ans[i]].first.second);
//cout << edges[ans[i]].first.first << " " << edges[ans[i]].first.second << endl;
}
}
return 0;
}