题目:
分析:最小生成树就两种方法。
提醒一个要点,因为是树,所以可能以点计数,也可能以边计数。
Kruskal(克鲁斯卡尔)~边:
1.边排序。
2.按顺序加入并判断不能成环,以并查集来判断。
首先使用结构体+cmp:
#include<bits/stdc++.h>
using namespace std;
int m,n;
struct edge{
int start,end;
int len;
};
bool cmp(edge a,edge b)
{
return a.len>b.len;
}
vector<edge> v;
int main()
{
cin>>m>>n;
for(int i=0;i<n;i++)
{
int a,b,c;
cin>>a>>b>>c;
struct edge e;
e.start=a;
e.end=b;
e.len=c;
v.push_back(e);
}
sort(v.begin(),v.end(),cmp);
for(int i=0;i<v.size();i++)
{
cout<<v[i].len<<' ';
}
}
加入并查集来判断,新的边是否可以加入。
和题解差不多,竟然有错???一脸冥币:
#include<bits/stdc++.h>
using namespace std;
int m,n;
int fa[5005];
struct edge{
int start,end;
long long len;
} v[200005];
bool cmp(edge a,edge b)
{
return a.len<b.len;
}
int find(int x)
{
if(fa[x]==x) return x;
fa[x]=find(fa[x]);
return fa[x];
}
int main()
{
cin>>m>>n;
for(int i=0;i<n;i++)
{
int a,b,c;
cin>>a>>b>>c;
v[i].start=a;
v[i].end=b;
v[i].len=c;
}
sort(v,v+n,cmp);
for(int i=1;i<=m;i++) fa[i]=i;
int num=0;
int ans=0;
for(int i=0;i<n;i++)
{
if(find(v[i].start)==find(v[i].end)) continue;
num++;
fa[find(v[i].start)]=find(v[i].end);
ans+=v[i].len;
if(num+1==m) break;
}
cout<<ans;
}
第二种方法,从一个点出发。
我觉得自己的代码思路很好。代码写的也非常的简练,很好
思路:
和地杰斯特拉算法差不多:
1.以一个集合来存放已经确定的点。
2.首先加入一个点,然后该点的边全部加入队列。
3.取出队列首个,如果两个点都加入,取下一个。
只有一个加入,则改变确定,另一个点确定,另一个点加入到确定点集合,并且该点所有的边加入到队列。(可以优化的一步是:加入的边的另一个点未加入已确定点集合才有必要加入队列)
ac代码:
#include<bits/stdc++.h>
using namespace std;
int m,n;
struct node{
int e1;
int e2;
int len;
bool operator < (const node & x) const
{
return x.len<len;
}
};
priority_queue<node> q;
vector<vector<node> > vvn;
set<int> s;
int ans=0;
int main()
{
cin>>m>>n;
vector<node> vn;
for(int i=0;i<=m;i++) vvn.push_back(vn);
for(int i=0;i<n;i++)
{
int a,b,c;
cin>>a>>b>>c;
struct node nn;
nn.e1=a;
nn.e2=b;
nn.len=c;
vvn[a].push_back(nn);
vvn[b].push_back(nn);
}
s.insert(1);
for(int i=0;i<vvn[1].size();i++)
{
q.push(vvn[1][i]);
}
while(s.size()!=m)
{
struct node nn=q.top();
q.pop();
if(s.count(nn.e1)==1&&s.count(nn.e2)==1) continue;
ans+=nn.len;
int c;
if(s.count(nn.e1)==1) c=nn.e2;
else c=nn.e1;
s.insert(nn.e1);
s.insert(nn.e2);
for(int i=0;i<vvn[c].size();i++)
{
if(s.count(vvn[c][i].e1)&&s.count(vvn[c][i].e2)) continue;
q.push(vvn[c][i]);
}
}
cout<<ans;
}