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代碼
維基百科並查集路徑優化