Prim算法
洛谷p3366最小生成树模版题
Prim算法基于点,在无向图中每次选择离已生成的树最近的一个未加入点加入树,随后更新未加入的点的距离。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=5010,MAXM=400010;
struct line
{
int y,next,w;
}l[MAXM];
int f[MAXN]={0},n,m,num=0;
int flag[MAXN]={0},sum=0,dis[MAXN];
inline void init()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
l[++num].y=b;
l[num].w=v;
l[num].next=f[a];
f[a]=num;
l[++num].y=a;
l[num].w=v;
l[num].next=f[b];
f[b]=num;
}
return;
}
inline void prim()
{
memset(dis,10,sizeof(dis));
dis[1]=0;
for(int i=1;i<=n;i++)
{
int mi=1000000,k=0;
for(int j=1;j<=n;j++)
if(flag[j]==0&&dis[j]<mi)//寻找最近的未加入点
{
mi=dis[j];
k=j;
}
if(k==0)//没有找到,说明图不连通
{
printf("orz");
exit(0);
}
flag[k]=1;
sum+=dis[k];//累加权值
for(int j=f[k];j;j=l[j].next)
if(l[j].w<dis[l[j].y])
dis[l[j].y]=l[j].w;//更新距离
}
printf("%d",sum);
return;
}
int main()
{
init();
prim();
return 0;
}
Kruskal算法
洛谷p1547失去的干草(误
Kruskal算法基于边与并查集的操作,从权值小到大搜索边,如果边连接的两点不属于同一集合就合并。
理解了并查集后,这个还是非常简单的。
#include<bits/stdc++.h>
using namespace std;
struct line
{
int x,y;
int w;
}l[10010];
int n,m,fa[2010],ans;
inline int read()
{
int num=0;
char c=getchar();
for(;c<'0'||c>'9';c=getchar());
for(;c>='0'&&c<='9';c=getchar())num=num*10+c-'0';
return num;
}
inline bool mycmp(line a,line b)
{
return(a.w<b.w);
}
inline int getfather(int x)//找父亲顺便压缩路径
{
if(fa[x]==x)return x;
fa[x]=getfather(fa[x]);
return fa[x];
}
void init()
{
n=read();m=read();
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
l[i].x=read();
l[i].y=read();
l[i].w=read();
}
sort(l+1,l+m+1,mycmp);//排序
return;
}
void work()
{
int flag=0;
for(int i=1;i<=m;i++)
{
int tx=getfather(l[i].x);
int ty=getfather(l[i].y);
if(tx!=ty)
{
fa[tx]=ty;
flag++;
ans=l[i].w;//更新当前最长边
if(flag==n-1)return;//如果加入的边达到要求
}
}
return;
}
int main()
{
init();
work();
printf("%d",ans);
return 0;
}