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代码
维基百科并查集路径优化