1.知识点复习:并查集,最小生成树(prime和克鲁斯卡尔)算法.
并查集
void init(int x)//初始化
{
for(int i=1;i<=x;i++)
{
f[i]=i;
rank[i]=1;
}
}
int find(int x)
{
if(x==f[x])
return x;
else {//路径压缩
f[x]=find(f[x]);
return f[x];
}
/*非路径压缩
else{
return find(f[x]);
}
*/
}
//按序合并
void merge(int x,int y)
{
int n=find(x),m=find(y);
if(rank[n]==rank[m]) {
f[m]=n;rank[n]++;
}
if(rank[n]>rank[m]){
f[m]=n;
}
else f[n]=m;
}
//按序合并与路径压缩一般不一起用。
void merge1(int x,int y)
{
int n=find(x),m=find(y);
f[n]=m;
} 克鲁斯卡尔算法写最小生成树要用到并查集(数据大时一定要用路径压缩)。
prime算法模板
int prime(int n,int st)
{
int cnt=st;
vis[st]=1;//标记起点并记录他
for(int i=1;i<=n;i++)
{
if(i==st) dis[st]=0;
else dis[i]=mp[i][st];
}
//更新dis
for(int i=1;i<n;i++)//再找接下来的n个点
{
int mini=min_n;
for(int j=1;j<=n;j++)//找到目前未归类的最短路径连接的点
{
if(vis[j]==0&&mini>dis[j])
{
mini=dis[j];
cnt=j;
}
}
ans+=dis[cnt];
vis[cnt]=1;
for(int j=1;j<=n;j++)//更新路径
if(vis[j]==0&&dis[j]>mp[cnt][j])//以目前找到的点为起点更新dis
dis[j]=mp[cnt][j];
/*迪杰斯特拉
if(vis[j]==0&&dis[j]>mp[cnt][j]+dis[cnt])
dis[j]=mp[cnt][j]+dis[cnt];
*/
}
} 由于prime算法与迪杰斯特拉思路相似,重新写一下思路复习两个算法。将已经连接的点与未连接的点设定两个集合,用vis[ ]数组标记是否找到,vis[]=1表示找到。每次从vis[]=0的集合里找到一个距离vis[]=1集合最近的点,并更新dis[].迪杰斯特拉与prime算法的不同处就在于更新dis的操作。
用线段树完成动态最小生成树



京公网安备 11010502036488号