洛谷:P3366 【模板】最小生成树(基础总结,图)

题目:

洛谷:P3366 【模板】最小生成树(基础总结,图)_第1张图片

分析:最小生成树就两种方法。

提醒一个要点,因为是树,所以可能以点计数,也可能以边计数。

Kruskal(克鲁斯卡尔)~边:

1.边排序。

2.按顺序加入并判断不能成环,以并查集来判断。

首先使用结构体+cmp:

#include
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
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=0;i
 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<<"      "<
 }
 cout<<ans;
}

第二种方法,从一个点出发。

我觉得自己的代码思路很好。代码写的也非常的简练,很好

思路:

和地杰斯特拉算法差不多:

1.以一个集合来存放已经确定的点。

2.首先加入一个点,然后该点的边全部加入队列。

3.取出队列首个,如果两个点都加入,取下一个。

只有一个加入,则改变确定,另一个点确定,另一个点加入到确定点集合,并且该点所有的边加入到队列。(可以优化的一步是:加入的边的另一个点未加入已确定点集合才有必要加入队列)

ac代码:

#include
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;
}

你可能感兴趣的:(我认为的精华,图)