最开始就想写并查集的,但觉得有点复杂,于是停了好几天,今天看了看以前写的题发现并查集一般都和最小生成树一起出现,所以,今天也就是把最小生成树的模板带过来,顺便把并查集写了:
int par[N]; //根节点
int hight[N]; //树的高度
struct edge
{
int u,v,cost;
};
edge G[N];
int E,V;//边数和顶点数
void Init_union_find(int n)//初始化根节点
{
for(int i=0; i<=n; i++)
{
par[i]=i;
hight[i]=0;
}
}
int find(int x) //找根节点
{
if(par[x]==x)
return x;
else
return par[x]=find(par[x]);
}
void unite(int x,int y) //连结整个图
{
x=find(x);
y=find(y);
if(x==y)
return ;
if(hight[x]<hight[y])
par[x]=y;
else
{
par[y]=x;
if(hight[x]==hight[y])
hight[x]++;
}
}
bool same(int x,int y)
{
return find(x)==find(y);
}
bool cmp(edge a,edge b) //以花费来做个升序排列,每次都是最少的那个关系
{
return a.cost<b.cost;
}
int kruskal()
{
sort(G,G+E,cmp);
Init_union_find(V);
int ans=0;
for(int i=0; i<E; i++)
{
edge e=G[i];
if(!same(e.u,e.v))
{
unite(e.u,e.v);
ans+=e.cost;
}
}
return ans;
}
其实最大的问题就是我其实只会克鲁卡尔这一种算法,还有一种prim算法没看
并查集:
int pre[1005]; void chushihua() { for(int i=1;i<=N;i++) pre[i]=i; } int find(int x) { int r=x; while(pre[r]!=r) r=pre[r]; int i=x,j; while(i!=r) { j=pre[i]; pre[i]=r; i=j; } return r; } void join(int x,int y) { int fx=find(x); int fy=find(y); if(fx!=fy) pre[fx]=fy; }