1.最小生成树
将所有的边从小到大排序,再用并查集查看是否有环
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int x,y,z;
}edge[501000];
int fa[501000];
int sum=0;
bool cmp(node a,node b)
{
return a.z<b.z;
}
int get(int x)
{
return x==fa[x]?x:fa[x]=get(fa[x]);
}
int main()
{
int n,m;
cin >> n >> m;
for(int i=1;i<=m;i++)
{
cin >> edge[i].x >> edge[i].y >> edge[i].z;
}
for(int i=0;i<=n;i++)
fa[i]=i;
sort(edge+1,edge+m+1,cmp);
for(int i=1;i<=m;i++)
{
int x=get(edge[i].x);
int y=get(edge[i].y);
if(x==y)continue;
fa[y]=x;
sum+=edge[i].z;
}
int ans=0;
for(int i=1;i<=n;i++)
if(i==fa[i])ans++;
if(ans>1)cout << "orz";
else cout << sum;
}
2.无线通讯网
一个卫星节点可节约一条边,我们节约较大的边,即找边时减去
#include <bits/stdc++.h>
using namespace std;
struct node
{
double z, x,y;
}edge[501000];
int fa[501000];
int a[501000];
int b[501000];
double sum=0;
bool cmp(node a,node b)
{
return a.z<b.z;
}
int find(int x)
{
if(x!=fa[x])
{
fa[x]=find(fa[x]);
}
return fa[x];
}
void unity(int x, int y)
{
int r1=find(x);
int r2=find(y);
fa[r1]=r2;
}
int main()
{
int n,m;
cin >> n >> m;
int p=0;
for(int i=1;i<=m;i++)
{
cin >> a[i] >> b[i];
for(int j=1;j<i;j++)
{
p++;
edge[p].x=i;
edge[p].y=j;
edge[p].z=sqrt((a[i] - a[j]) * (a[i] - a[j]) + (b[i] - b[j]) * (b[i] - b[j]));
}
}
for(int i=1;i<=m;i++)
fa[i]=i;
sort(edge+1,edge+p+1,cmp);
int k=0;
for(int i=1;i<=p;i++)
{
if(find(edge[i].x)!=find(edge[i].y))
{
unity(edge[i].x,edge[i].y);
sum=edge[i].z;
k++;
if(k>=m-n)
{
printf("%.2lf",sum);
return 0;
}
}
}
}
3.拆地毯
从大到小排序,利用模板
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int x,y,z;
}edge[501000];
int fa[501000];
int sum=0;
bool cmp(node a,node b)
{
return a.z>b.z;
}
int get(int x)
{
return x==fa[x]?x:fa[x]=get(fa[x]);
}
int main()
{
int n,m,k;
cin >> n >> m>>k;
for(int i=1;i<=m;i++)
{
cin >> edge[i].x >> edge[i].y >> edge[i].z;
}
for(int i=1;i<=n;i++)
fa[i]=i;
sort(edge+1,edge+m+1,cmp);
int s=0;
for(int i=1;i<=n;i++)
{
int x=get(edge[i].x);
int y=get(edge[i].y);
if(x==y)continue;
fa[y]=x;
sum+=edge[i].z;
s++;
if(s>=k)
{
cout << sum;
return 0;
}
}
}