并查集其实就是树,白书上其实有详细说明
//最开始每个人都是自己的老板
//也就是每个人都是独立的集合
//非递归方式
void Init(int person)
{
myboss[person]=person;
}
//非递归找老板
int find_boss(int person)
{
int boss = person;
while(boss!=myboss[boss])
{
boss=my[boss];
}
//路径压缩
int leader=person;
while(leader!=boss)
{
tmp=myboss[leader];
myboss[leader]=boss;
leader=tmp;
}
return leader;
}
//递归找老板
int find_boss(int person)
{
if(person!=myboss[person])
myboss[person]=find_boss(myboss[person]);
return myboss[person];
}
void Union(int person1,int person2)
{
int boss1=find_boss(person1);
int boss2=find_boss(person2);
if(boss1!=boss2)
{
myboss[boss1]=boss2;
}
}
克鲁斯卡尔算法要判断两条边在不在一个集合,所以要用到并查集,比较适用于稀疏图
#include <iostream>
#include <algorithm>
using namespace std;
struct edge{
int from;
int to;
int weight;
};
int myboss[500];
edge e[50000];
int ans;
bool cmp(const edge &a, const edge &b)
{
return a.weight < b.weight;
}
void Init(int n)
{
for(int i = 1; i <= n; i++)
myboss[i] = i;
}
int find_boss(int person)
{
if(person != myboss[person])
myboss[person] = find_boss(myboss[person]);
return myboss[person];
}
bool Union(int person1,int person2)
{
person1 = find_boss(person1);
person2 = find_boss(person2);
if(person1 != person2)
{
myboss[person1]=person2;
return true;
}
return false;
}
void Kruskal(int k,int m,int n)
{
int u,v;
for(int i = 1; i <= m; i++)
{
u = e[i].from;
v = e[i].to;
if(Union(u,v))
{
k++;
ans += e[i].weight;
}
}
if(k == n-1)
cout << ans <<endl;
return ;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n,m=0,t,k=0;
int already;
cin>>n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <=n; j++)
{
cin>>t;
if(i != j)
{
m++;
e[m].from = i;
e[m].to = j;
e[m].weight = t;
}
}
}
sort(e + 1, e + m + 1, cmp);
cin>>already;
int u,v;
Init(n);
for(int i = 1; i <= already; i++)
{
cin>>u>>v;
if(Union(u,v))
k++;
}
Kruskal(k,m,n);
return 0;
}
prim算法和dij算法其实很像,比较适用于稠密图
void Prim(int v)
{
memset(visit,false,sizeof(visit));
for(int i=1;i<=n;i++)
dist[i] = acs[v][i];
dist[v]=0;
visit[v]=true;
for(int i=2;i<=n;i++)
{
int minor=0x3f,index;
for(int j=1;j<=n;j++)
{
if(!visit[j]&&dist[j]<minor)
{
index=j;
minor=dist[j];
}
}
visit[index]=true;
e++;
ans+=minor;
for(int k=1;k<=n;k++)
{
if(!visit[k]&&dist[k]>acs[index][k])
{
dist[k]=acs[index][k];
}
}
}
if(e==n-1)
cout<<ans<<endl;
else
cout<<"0";
e=0;
ans=0;
return ;
}