P3366 【模板】最小生成树
Prim
处理了重复边和环 + 无法找到最小生成树的判别
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 5010;
const int inf = 0x3f3f3f3f;
int dis[N];
int vis[N];
int a[N][N];
int n,m;
int res = 0;
void Init()
{
memset(a,0x3f,sizeof(a));
memset(dis,0x3f,sizeof(dis));
}
bool Prim(int u)
{
dis[u] = 0;
for(int i=1;i<=n;i++)
{
int k=-1;
int MIN = inf;
for(int j=1;j<=n;j++)
if(!vis[j] && dis[j] < MIN)
{
MIN = dis[j];
k=j;
}
if(k==-1) return false; //找不到最小的了,说明有环。
vis[k] = 1;
res +=MIN;
for(int j=1;j<=n;j++)
{
if(dis[j] > a[k][j] &&a[k][j] !=0 &&!vis[j])
dis[j] = a[k][j];
}
}
return true;
}
int main()
{
Init();
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,d;
cin>>x>>y>>d;
a[x][y] = a[y][x] = min(a[x][y],d); //防止有重复边
}
for(int i=1;i<N;i++) a[i][i] = 0; //防止有环
if(Prim(1))
cout<<res;
else cout<<"orz";
}
Kruscal算法
简单点,没有什么大的注意事项。
注意判断生成最小生成树的判别是n个点的图有没有生成n-1条边。
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 2e5+10;
int f[N];
int ans = 0;
struct edge{
int u,v;
int w;
bool operator<(const struct edge &a)
{
return w<a.w;
}
}e[N];
int n,m;
void Init()
{
for(int i=1;i<N;i++) f[i] = i;
}
int find(int x)
{
if(x==f[x]) return x;
return f[x] = find(f[x]);
}
void Union(int a,int b)
{
a=find(a);
b=find(b);
f[a] = b;
}
int main()
{
Init();
int num=0;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,w;
cin>>x>>y>>w;
e[i].u=x;
e[i].v=y;
e[i].w=w;
}
sort(e+1,e+1+m);
for(int i=1;i<=m;i++)
{
int x,y,w;
x=e[i].u;
y=e[i].v;
w=e[i].w;
if(find(x)!=find(y))
{
num++;
ans += w;
Union(x,y);
}
}
if(num==n-1) cout<<ans; //n个点的最小生成树有 n-1条边。
else cout<<"orz";
}