您的位置:首页 > 其它

【2018寒假集训Day 8】【最小生成树】Prim和Kruskal算法模板

2018-02-08 21:14 519 查看
Luogu最小生成树模板题

Prim

原理与dijkstra几乎相同,每次找最优的点,用这个点去松弛未连接的点,也就是用这个点去与未连接的点连接。

#include<cstdio>
#include<vector>
using namespace std;
struct data
{
int to,val;
};
vector<data> edge[200001];
int n,m,cost[5001],ans;
bool visit[5001];
void add(int x,int y,int z)
{
data tmp;
tmp.to=y;
tmp.val=z;
edge[x].push_back(tmp);
}
void init()
{
scanf("%d%d",&n,&m);
int x,y,z;
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
}
void First()
{
for (int i=1;i<=n;i++) cost[i]=0xfffffff;
cost[1]=0;
}
void prim()
{
for (int i=1;i<=n;i++)
{
int mincost=0xfffffff;
int mini=0;
for (int j=1;j<=n;j++)
if (mincost>cost[j]&&!visit[j]) mincost=cost[j],mini=j;
visit[mini]=true;
ans+=cost[mini];
for (int j=0;j<edge[mini].size();j++)
if (!visit[edge[mini][j].to]&&cost[edge[mini][j].to]>edge[mini][j].val)
cost[edge[mini][j].to]=edge[mini][j].val;
}
}
int main()
{
init();
First();
prim();
printf("%d",ans);
return 0;
}


Kruskal

运用并查集,存储边,以权值为关键字进行排序,从小到大查看边,如果这条边的两个点不在同一集合内,就加入同一集合并压缩路径。

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
struct data
{
int str,to,val;
}edge[200001];
int n,m,father[5001],ans,cnt;
bool comp(data a,data b)
{
return a.val<b.val;
}
void init()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&edge[i].str,&edge[i].to,&edge[i].val);
}
}
int getfather(int v)
{
if (father[v]!=v) father[v]=getfather(father[v]);
return father[v];
}
void hb(int x,int y)
{
x=getfather(x);
y=getfather(y);
father[x]=y;
}
bool check(int a,int b)
{
a=getfather(a);
b=getfather(b);
if (a==b) return true;
return false;
}
int main()
{
init();
for (int i=0;i<=n;i++)
father[i]=i;
sort(edge+1,edge+1+m,comp);
for (int i=1;i<=m;i++)
{
if (!check(edge[i].str,edge[i].to))
{
hb(edge[i].str,edge[i].to);
ans+=edge[i].val;
cnt++;
}
}
if (cnt<n-1) printf("orz");
else printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: