http://ac.jobdu.com/problem.php?pid=1347
用getchar读取数据居然可以少这么多,比起scanf整整少了320ms
并查集优化:
(1)路径压缩
我们找到最久远的祖先时“顺便”把它的子孙直接连接到它上面
int findSet(int x){
if(fa[x]==-1)
return x;
int ret=findSet(fa[x]);
fa[x]=ret;
return ret;
}
(2)
Rank合并
合并时将元素所在深度低的集合合并到元素所在深度高的集合
void unionSet(int x,int y,int dd){
int root1=findSet(x);
int root2=findSet(y);
if(root1!=root2){
sum+=dd;
cnt++;
if(rank[root1]<rank[root2]){
fa[root1]=root2;
}
else{
fa[root2]=root1;
if(rank[root1]==rank[root2])
rank[root1]++;
}
}
}
// 题目1343:城际公路网.cpp: 主项目文件。
#include "stdafx.h"
#include <cstdio>
#include <vector>
#include <algorithm>
using std::sort;
using std::vector;
const int N=1003;
int fa[N],rank[N];
typedef struct Edge{
int u,v,dd;
Edge(int _u,int _v,int _dd):u(_u),v(_v),dd(_dd){}
}Edge;
vector<Edge> edge;
int n,sum,cnt;
bool cmp(Edge m1,Edge m2){
return m1.dd<m2.dd;
}
inline void read(int &d){
char ch=getchar();
while(ch<'0'||ch>'9')
ch=getchar();
d=0;
do{
d=d*10+ch-'0';
ch=getchar();
}while(ch>='0'&&ch<='9');
}
void init(){
for(int i=1;i<=n;i++){
fa[i]=-1;
rank[i]=1;
}
}
int findSet(int x){
if(fa[x]==-1)
return x;
int ret=findSet(fa[x]);
fa[x]=ret;
return ret;
}
void unionSet(int x,int y,int dd){
int root1=findSet(x);
int root2=findSet(y);
if(root1!=root2){
sum+=dd;
cnt++;
if(rank[root1]<rank[root2]){
fa[root1]=root2;
}
else{
fa[root2]=root1;
if(rank[root1]==rank[root2])
rank[root1]++;
}
}
}
void kruskal(){
sum=0,cnt=0;
for(vector<Edge>::iterator ite=edge.begin();ite!=edge.end();++ite)
unionSet(ite->u,ite->v,ite->dd);
if(cnt==n-1)
printf("%d\n",sum);
else
printf("no\n");
}
int main()
{
int m;
while(~scanf("%d%d",&n,&m)){
edge.clear();
for(int i=0;i<m;i++){
int u,v,dd;
read(u),read(v),read(dd);
Edge e(u,v,dd);
edge.push_back(e);
}
sort(edge.begin(),edge.end(),cmp);
init();
kruskal();
}
return 0;
}
参考:
九度kingwolfofsky代码
维基百科并查集路径优化