20 solutions

  • 8
    @ 2021-9-14 20:38:38

    使用 Kruskal 算法解决。

    主要思路:把边以边权从小到大排序。接下来从头开始枚举边。如果边会使得后面的图一定不是树(即出现环),则跳过。如果总共已经 n1n-1 条边,则结束。如果所有枚举完后不到 n1n-1 条边,则返回不行(此题没有)。

    那么如何判断是否有环?最好的方法就是使用优化的并查集。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int m,n,cnt,sum;
    int fa[100009];
    struct edge{
        int w;
        int u,v;
    };
    edge e[200009];
    bool cmp(edge x,edge y){
        return x.w<y.w;
    }
    void init(){
        cin>>n>>m;
        for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
        for(int i=1;i<=n;i++) fa[i]=i;
    }
    int anc(int k){
        if(fa[k]==k) return k;
        else return fa[k]=anc(fa[k]);
    }
    void relate(int x,int y){
        if(x<y) swap(x,y);
        fa[anc(y)]=anc(x);
    }
    signed main(){
        init();
        sort(e+1,e+m+1,cmp);
        for(int i=1;i<=m;i++){
            if(anc(e[i].u)!=anc(e[i].v)){
                cnt++;
                relate(e[i].u,e[i].v);
                sum+=e[i].w;
            }
            if(cnt==n-1) break;
        }
        if(cnt!=n-1) cout<<"No solution";
        else cout<<sum;
        return 0;
    }
    
    • 4
      @ 2022-11-11 19:39:56

      怎么都不约而同地使用 Kruskal 去了,堆优化的 Prim 也可以通过这一题的。

      Prim 算法是什么 & 算法原理

      Prim 算法与最短路中的 Dijsktra 算法有点相像。我们随便选取一个根,接下来从根节点向外贪心地选取最小的边,将其加入至最小生成树中即可,其中,选取最小的边的操作可以用堆优化至 O(logn)O(\log n)

      总的复杂度:O(nlogn)O(n\log n)

      #include <bits/stdc++.h>
      using namespace std;
      
      #define endl '\n'
      #define int long long
      #define lson (p << 1)
      #define rson ((p << 1) | 1)
      #define mid ((l + r) >> 1)
      
      const int MAXN = 1e5 + 5;
      struct _node {
          int v, w;
          bool operator < (const _node b) const {
              return w > b.w;
          }
      };
      vector<_node> G[MAXN];
      int n, m, dis[MAXN];
      bool vis[MAXN];
      
      int prim() {
          int cnt = 0, ret = 0;
          memset(dis, 0x3f, sizeof dis);
          priority_queue<_node> pq;
          pq.push({1, 0});
          while (pq.size() && cnt < n) {
              auto [u, w] = pq.top(); pq.pop();
              if (vis[u]) continue;
              cnt++; ret += w;
              vis[u] = true;
              for (auto [v, x]:G[u]) {
                  if (x < dis[v]) {
                      dis[v] = x;
                      pq.push({v, dis[v]});
                  }
              }
          }
          return ret;
      }
      
      signed main(void) {
          ios::sync_with_stdio(false);
          cin.tie(0);
          cin >> n >> m;
          for (int i = 1; i <= m; ++i) {
              int u, v, w;
              cin >> u >> v >> w;
              G[u].push_back({v, w});
              G[v].push_back({u, w});
          }
          cout << prim() << endl;
          return 0;
      }
      
    • 4
      @ 2022-7-19 17:57:50

      这里讲解一下 KruskalKruskal算法。

      KruskalKruskal的主要思想:贪心。

      既然我要求的是最小权值,那么我对所有边进行排序,然后一条一条看就行了。

      那么怎么样的边是可选的呢?

      很显然,如果一边上两个点(未连接时)在两个连通分量中,那么这条边是可选的(毕竟不连白不连);而如果这两点在一个连通分量中,那么这条边就不可选了。

      最后,因为树的权值最小,当边数为 n1n-1时,程序结束。

      注意权值数据范围。

      代码如下:

      #include<bits/stdc++.h>
      #define maxn 200005
      using namespace std;
      int n,m,s,cnt=1,fa[maxn];
      struct Edge{
          int u,v,w;
      } e[maxn];
      int find(int k){
          if(fa[k]==k)return k;
          return fa[k]=find(fa[k]);
      }
      bool cmp(Edge a,Edge b){
          return a.w<b.w;
      }
      int main(){
          cin>>n>>m;
          for(int i=1;i<=n;i++)fa[i]=i;
          for(int i=1;i<=m;i++)
              cin>>e[i].u>>e[i].v>>e[i].w;
          sort(e+1,e+m+1,cmp);
          for(int i=1;i<=m&&cnt<n;i++){
              int u=e[i].u,v=e[i].v;
              if(find(u)==find(v))continue;
              s+=e[i].w;
              cnt++;
              fa[find(u)]=find(v);
          }if(cnt<n)cout<<-1;
          else cout<<s;
          return 0;
      }
      
      • 3
        @ 2022-2-19 13:30:24

        使用 Kruskal 解决。

        Kruskal 使用的是一个贪心算法,首先把边权按从小到大排序,然后依次加边,如果加出了环,那就不加了。如果有 n1n-1 条边那么就已经得出答案。

        证明:如果有一条边 uu 删除后可以用其他边 vv 顶替,根据排序方法可知 uvu\le v,也就是说,换上 vv 之后不能使答案变优。

        注意最终答案最大可以在 101110^{11} 的级别,需要开 long long

        代码瓶颈在排序,时间复杂度 O(mlogm)O(m\log m)

        #include<bits/stdc++.h>
        #define int long long
        using namespace std;
        const int maxn=2e5+5;
        int father[maxn],m,n,u,v,w,ans;
        struct edge{
        	int x,y,z;
        	bool operator <(const edge &a) const{
        		return z<a.z;
        	}
        };
        vector<edge> G;
        void makeSet(int n){
        	for(int i=1;i<=n;i++)
        		father[i]=i;
        }
        int findSet(int x){
        	if(father[x]==x)
        		return x;
        	return father[x]=findSet(father[x]);
        }
        void Kruskal(){
        	makeSet(n);
        	sort(G.begin(),G.end());
        	int edgeNum=0;
        	for(int i=0;i<m;i++){
        		int x=findSet(G[i].x),y=findSet(G[i].y);
        		if(x!=y){
        			father[x]=y;
        			ans+=G[i].z;
        			edgeNum++;
        		}
        		if(edgeNum==n-1)
        			return;
        	}
        }
        signed main(){
        	scanf("%lld%lld",&n,&m);
        	for(int i=1;i<=m;i++){
        		scanf("%lld%lld%lld",&u,&v,&w);
        		G.push_back(edge({u,v,w}));
        	}
            Kruskal();
        	printf("%lld\n",ans);
        	return 0;
        }
        
        • 2
          @ 2026-1-16 16:32:01

          算法:最小生成树\color{lightgreen}\texttt{最小生成树}

          其实,本题为克鲁斯卡尔算法,步骤如下

          • 每条边按边权排序\texttt{每条边按边权排序}
          • 一个一个枚举边,形成环则跳过,否则加上这条边\texttt{一个一个枚举边,形成环则跳过,否则加上这条边}
          • 输出答案\texttt{输出答案}

          如何判环,用dsu\color{silver}\texttt{dsu}维护即可

          stable_sort(begin,end,compare)是为了不让sort爆掉。

          最后十年OI一场空,不开long    long见祖宗\texttt{\color{red}十年OI一场空,不开long\;\;long见祖宗}

          代码如下

          #include<bits/stdc++.h>
          using namespace std;
          int n;
          int c[1001];
          struct edg{
              int sta,to,w;
          };
          vector<edg> g;
          bool cmp(edg a,edg b){
              return a.w<=b.w;
          }
          int fa[1002];
          int find(int x){
              if(x!=fa[x]){
                  int k=find(fa[x]);
                  fa[x]=k;
                  return k;
              }
              else {
                  return x;
              }
          }
          bool ingraph[1002];
          int pans=29184631;
          signed main(){
          
              cin>>n;
              for(int i=1;i<=n;i++) cin>>c[i],pans=min(pans,c[i]);
              for(int i=1;i<=n;i++){
                  for(int j=1;j<=n;j++){
          
                      int w;
                      cin>>w;
                      if(i!=j) g.push_back({i,j,w});
                      g.push_back({i,n+1,c[i]});
                      g.push_back({n+1,i,c[i]});
                  }
              }
              stable_sort(g.begin(),g.end(),cmp);
              int cnt=0;
              int minn=0;
              for(int i=1;i<=n+1;i++) fa[i]=i;
              for(int i=0;i<g.size();i++){
                  int x=g[i].sta;
                  int y=g[i].to;
                  int w=g[i].w;
                  int k1=find(x);
                  int k2=find(y);
                  if(k1==k2) continue;
                  cnt+=2;
                  if(ingraph[k1]==true){
                      cnt-=1;
                  }
                  if(ingraph[k2]==true){
                      cnt-=1;
                  }
                  ingraph[k1]=ingraph[k2]=true;
                  fa[k2]=k1;
                  minn+=w;
                  if(cnt==n+1) break;
              }
              cout<<minn;
          }
          
          • 2
            @ 2026-1-3 17:30:07

            一道经典的最小生成树模板题,我们考虑使用 kruskal 算法。

            kruskal 算法:

            这个算法的核心思路是把边以边权从小到大排序,依次枚举边,如果此边加入后会形成环,则跳过。若共有 n1n-1 条边,就结束。

            如何判断会不会形成环?也许可以打标记,不过更常用的是并查集。

            并查集其实就是个路径压缩。

            上代码:

            
            ```cpp
            #include<bits/stdc++.h>
            #define int long long
            using namespace std;
            int n,m,fa[100005],ans,cnt;
            struct edge{
                int u,v,w;
            }E[200005];
            inline bool cmp(edge a,edge b){
                return a.w<b.w;
            }
            int finds(int x){
                if(fa[x]==x) return x;
                return fa[x]=finds(fa[x]);
            }
            void kruskal(){
                sort(E+1,E+m+1,cmp);
                for(int i=1;i<=m;i++){
                    int u=finds(E[i].u),v=finds(E[i].v);
                    if(u==v) continue;
                    ans+=E[i].w,cnt++;
                    fa[u]=v;
                    if(cnt==n-1) break;
                }
            }
            signed main(){
                ios::sync_with_stdio(false);
                cin.tie(0),cout.tie(0);
                cin>>n>>m;
                for(int i=1;i<=n;i++) fa[i]=i;
                for(int i=1;i<=m;i++) cin>>E[i].u>>E[i].v>>E[i].w;
                kruskal();
                cout<<ans;
                return 0;
            }
            
            • 2
              @ 2024-12-28 17:22:44
              
              ```#include<bits/stdc++.h>
              using namespace std;
              #define int long long
              int m,n,cnt,sum;
              int fa[100009];
              struct edge{
                  int w;
                  int u,v;
              };
              edge e[200009];
              bool cmp(edge x,edge y){
                  return x.w<y.w;
              }
              void init(){
                  cin>>n>>m;
                  for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
                  for(int i=1;i<=n;i++) fa[i]=i;
              }
              int anc(int k){
                  if(fa[k]==k) return k;
                  else return fa[k]=anc(fa[k]);
              }
              void relate(int x,int y){
                  if(x<y) swap(x,y);
                  fa[anc(y)]=anc(x);
              }
              signed main(){
                  init();
                  sort(e+1,e+m+1,cmp);
                  for(int i=1;i<=m;i++){
                      if(anc(e[i].u)!=anc(e[i].v)){
                          cnt++;
                          relate(e[i].u,e[i].v);
                          sum+=e[i].w;
                      }
                      if(cnt==n-1) break;
                  }
                  if(cnt!=n-1) cout<<"No solution";
                  else cout<<sum;
                  return 0;
              }
              • 2
                @ 2023-11-16 15:53:45

                最小生成树个人喜欢 KruskalKruskal 算法

                前置知识:贪心,并查集

                原理

                最小生成树:一个无向连通图,边权值和最小的生成树

                既然是边权值和最小,那么我们可以用贪心的思想,将边权从小到大排序,依次插入最小生成树中。

                这是具体的排序后插入的操作:

                1. 如果 uuvv 两点之间没有路径,我们就将这条边加入到最小生成树中;
                2. 如果 uuvv 两点之间已经在最小生成树中有路径,或者形成了一个环,那么我们就把这条边"扔掉"。

                重复以上步骤,我们可以顺便统计最小生成树的边权和,直到最小生成树中有 n1n-1 条边(也就是构成了一棵树)。

                至于实现有无路径,我们可以使用并查集实现。

                这样子的时间复杂度最优是 O(mlogm)O(m \log{m})

                注意!!! 开long long!!!,0wi1060 \le w_i \le 10^6!!!

                这里提一嘴另一种求解最小生成树的方式:Prim,题解(link)可以参考楼下的 xiaoququ 大佬。

                它与 KruskalKruskal 的区别就在于一个是加点(Prim),一个是加边(Kruskal),而且 Prim 类似于最短路中的 Dijsktra 算法。

                AC code

                // Kruskal
                const int N = 2e5 + 5;
                typedef long long ll;
                
                struct Edge{
                	ll u, v, w;
                }e[N];
                
                bool cmp(Edge x, Edge y){
                	return x.w < y.w;
                }
                
                int find(int x){
                	if (fa[x] == x) return x;
                	return fa[x] = find(fa[x]);
                }
                
                int main(){
                
                	sort (e + 1, e + m + 1, cmp);
                	ll cnt = 0;
                	int tot = 0;
                	for (int i = 1; i <= m; ++i){
                		int u = e[i].u, v = e[i].v, w = e[i].w;
                		int fu = find(u), fv = find(v);
                		
                		if (fv == fu) continue;
                		fa[fu] = fv;
                		tot++;
                		cnt += w;
                		if (tot == n - 1) break;
                	}
                	return 0;
                }
                
                • 1
                  @ 2025-5-2 12:27:36

                  解题思路:

                  板子题,关于最小生成树

                  这里用 Kruskal 算法解决。

                  #include<bits/stdc++.h>
                  #define int long long
                  //注意开 long long。
                  using namespace std;
                  
                  
                  int n,m,cnt;
                  int fa[200005];
                  
                  struct node{
                  	int x,y,w;
                  }a[200005];
                  
                  int get(int x){
                  	if(x == fa[x])return x;
                  	return fa[x] = get(fa[x]);
                  }
                  
                  void unite(int x,int y){
                  	x = get(x);
                  	y = get(y);
                  	if(x != y)fa[x] = y;
                  }
                  
                  void inti(){
                     for(int i = 1 ; i <= m ; i++)fa[i] = i;
                  }
                  
                  bool cmp(node a,node b){
                  	return a.w < b.w;
                  }
                  
                  int ans;
                  
                  signed main(){
                  	ios::sync_with_stdio(false);
                  	cin.tie(0);
                  	cout.tie(0);
                  	cin >> n >> m;
                  	for(int i = 1 ; i <= m ; i++){
                  		cin >> a[i].x >> a[i].y >> a[i].w;
                  	}
                  	inti();
                  	sort(a + 1 , a + 1 + m , cmp);
                  	for(int i = 1 ; i <= m ; i++){
                  		if(get(a[i].x) != get(a[i].y)){
                  			unite(a[i].x,a[i].y);
                  			cnt++;
                  			ans += a[i].w;
                  			if(cnt == n - 1){
                  				cout << ans << '\n';
                  				return 0;
                  			}
                  		}else{
                  			continue;
                  		}
                  	}
                  	cout << "orz";//这个是啥不用管。
                  	return 0;
                  }
                  
                  • 1
                    @ 2024-6-1 18:33:12

                    在这里,我使用了 Kruskal 算法解决这道题(想看Prim算法的移步别的题解)。

                    思路:把边从边权大小从小到大排序,从 00 号开始遍历整个图,创建最小生成树,累加权值。使用一个优化后的并查集,如果所有边都在一个集中,则结束。输出权值总和。如果枚举完所有的点后仍达不到 n1n-1 条,则不行。

                    最后,我想提醒大家:

                    不开longlong,见!祖!宗!

                    代码(禁止抄袭!):

                    #include<bits/stdc++.h>
                    using namespace std;
                    int n,m,sum,cnt,f[200001];
                    struct node{
                    	int u,v,w;
                    }a[200001];
                    bool cmp(node x,node y){
                    	return x.w<y.w;
                    }
                    int find(int x){
                    	if(f[x]==x){
                    		return x;
                    	}
                    	return f[x]=find(f[x]);
                    }
                    int main(){
                    	scanf("%d%d",&n,&m);
                    	for(int i=1;i<=n;i++){
                    		f[i]=i;
                    	}
                    	for(int i=1;i<=m;i++){
                    		scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
                    	}
                    	sort(a+1,a+m+1,cmp);
                    	for(int i=1;i<=m;i++){
                    		if(find(a[i].u)!=find(a[i].v)){
                    			cnt++;
                    			sum+=a[i].w;
                    			f[find(a[i].u)]=find(a[i].v);
                    		}
                    	}
                    	if(cnt!=n-1){
                    		printf("orz");
                    		return 0;
                    	}
                    	printf("%d",sum);
                    	return 0;
                    }
                    
                    • 0
                      @ 2025-5-15 15:08:53

                      你说得对,但是克鲁斯卡尔好写

                      #include<bits/stdc++.h>
                      #define int long long
                      using namespace std;
                      int n,m;
                      struct edge{
                          int start,to;
                          int val;
                      }edg[2000005];
                      int fa[2000005];
                      int ans,s;
                      int temp=1;
                      int findroot(int x){
                          if(fa[x]==x) return x;
                          fa[x]=findroot(fa[x]);
                          return fa[x]; 
                      }
                      bool cmp(edge a,edge b){
                          return a.val<b.val;
                      }
                      void kruskal(){
                          for(int i=1;i<=m;i++){
                              int u=findroot(edg[i].start);
                              int v=findroot(edg[i].to);
                              if(u!=v){
                                  ans+=edg[i].val;
                                  fa[u]=v;
                                  s++;
                                  if(s==n-1){
                                      temp=0;
                                      return ;
                                  }
                              }
                          }
                      }
                      signed main(){
                          cin>>n>>m;
                          for(int i=1;i<=n;i++){
                              fa[i]=i;
                          }
                          for(int i=1;i<=m;i++){
                              cin>>edg[i].start>>edg[i].to>>edg[i].val;
                          }
                          sort(edg+1,edg+m+1,cmp);
                          kruskal();
                          if(temp==1){
                              cout<<"No";
                              return 0;
                          }
                          cout<<ans;
                          return 0;
                      }
                      
                      • 0
                        @ 2025-4-27 23:05:57
                        
                        #include<bits/stdc++.h>
                        #define int long long
                        #define endl '\n'
                        #define pr(x) pair<x,x>
                        #define up(i,j,k,l) for(int i=j;i<=k;i+=l)
                        #define down(i,j,k,l) for(int i=j;i>=k;i-=l)
                        using namespace std;
                        const int N=2e5+10;
                        int n,m;
                        struct node{
                        	int u,v,w;
                        };
                        node a[N];
                        int f[N],t1,t2,ans;
                        int fd(int x)
                        {
                        	if(x==f[x]){
                        		return x;
                        	}
                        	else{
                        		return f[x]=fd(f[x]);
                        	}
                        }
                        bool cmp(node x1,node x2)
                        {
                        	return x1.w<x2.w;
                        }
                        void solve()
                        {
                        	cin>>n>>m;
                        	up(i,1,n,1){
                        		f[i]=i;
                        	}
                        	up(i,1,m,1){
                        		cin>>a[i].u>>a[i].v>>a[i].w;
                        	}
                        	sort(a+1,a+m+1,cmp);
                        	up(i,1,m,1){
                        		t1=fd(a[i].u);
                        		t2=fd(a[i].v);
                        		if(t1!=t2){
                        			f[t1]=t2;
                        			ans+=a[i].w;
                        		}
                        	}
                        	cout<<ans<<endl;
                        	return;
                        }
                        signed main()
                        {
                            ios::sync_with_stdio(false);
                        	cin.tie(0);
                        	//freopen(".in","r",stdin);
                        	//freopen(".out","w",stdout);
                        	int _=1;
                        	//cin>>_;
                        	up(i,1,_,1){
                        		solve();
                        	}
                        	return 0;
                        }
                        
                        • 0
                          @ 2022-8-18 17:05:49

                          KruskalKruskal 解决问题,ansans 注意开 longlonglong long ,不然会爆

                          下面是 ACAC 代码:

                          #include<bits/stdc++.h>
                          using namespace std;
                          inline int read()
                          {
                              int x=0;
                              bool flag=1;
                              char c=getchar();
                              while(c<'0'||c>'9')
                              {
                                  if(c=='-')
                                      flag=0;
                                  c=getchar();
                              }
                              while(c>='0'&&c<='9')
                              {
                                  x=(x<<1)+(x<<3)+c-'0';
                                  c=getchar();
                              }
                              return (flag?x:~(x-1));
                          }
                          int n,m,k;
                          long long ans=0;
                          int f[100001];
                          struct edge
                          {
                          	int x,y,z;
                          }a[200001];
                          inline void init()
                          {
                          	for(int i=1;i<=n;i++)
                          	{
                          		f[i]=i;
                          	}
                          }
                          inline int find(int x)
                          {
                          	return x==f[x]?x:f[x]=find(f[x]);
                          }
                          inline bool cmp(edge a,edge b)
                          {
                              return a.z<b.z;
                          }
                          int main()
                          {
                          	n=read();m=read();
                          	init();
                          	for(int i=1;i<=m;i++)
                          	{
                          		int x,y,z;
                          		a[i].x=read();a[i].y=read();a[i].z=read();
                          	}
                          	sort(a+1,a+m+1,cmp);
                          	for(int i=1;i<=m;i++)
                          	{
                          		int fx=find(a[i].x),fy=find(a[i].y);
                          		if(fx==fy)
                          		{
                          			continue;
                          		}
                          		f[fx]=fy;
                          		ans+=a[i].z;	
                          	}
                          	cout<<ans;
                          	return 0;
                          }
                          

                          完结撒花!

                          • -1
                            @ 2023-3-25 9:36:19
                            #include<bits/stdc++.h>
                            using namespace std;
                            #define int long long
                            int m,n,cnt,sum;
                            int fa[100009];
                            struct edge{
                            int w;
                            int u,v;
                            };
                            edge e[200009];
                            bool cmp(edge x,edge y){
                            return x.w<y.w;
                            }
                            void init(){
                            cin>>n>>m;
                            for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
                            for(int i=1;i<=n;i++) fa[i]=i;
                            }
                            int anc(int k){
                            if(fa[k]==k) return k;
                            else return fa[k]=anc(fa[k]);
                            }
                            void relate(int x,int y){
                            if(x<y) swap(x,y);
                            fa[anc(y)]=anc(x);
                            }
                            signed main(){
                            init();
                            sort(e+1,e+m+1,cmp);
                            for(int i=1;i<=m;i++){
                            if(anc(e[i].u)!=anc(e[i].v)){
                            cnt++;
                            relate(e[i].u,e[i].v);
                            sum+=e[i].w;
                            }
                            if(cnt==n-1) break;
                            }
                            if(cnt!=n-1) cout<<"No solution";
                            else cout<<sum;
                            return 0;
                            }
                            
                            • -2
                              @ 2023-9-15 21:12:34

                              本题目可以用 最小生成树之 Kruskal 算法

                              #include <bits/stdc++.h>
                              
                              using namespace std;
                              
                              const int N = 1e5 + 10;
                              const int M = 2e5 + 10;
                              int fa[N], n, m;
                              long long ret; // 不开 long long 见祖宗
                              struct node {
                              	int x, y, z;
                              }e[M];
                              
                              bool cmp(node n1, node n2) {
                              	return n1.z < n2.z;
                              }
                              void INIT() { // 初始化每个节点的父节点都是自己
                              	for (int i = 1; i <= n; i++) {
                              		fa[i] = i; // 相当于一个图有 n 个节点,也有 n 个联通块
                              	} // 可以说是一个图没有边,初始化,Kruskal 的基本思想就是贪心
                              } 
                              int dfs(int x) { // 并查集,不懂看后面
                              	return fa[x] == x ? x : fa[x] = dfs(fa[x]);
                                  // fa[x] = dfs(fa[x]) 是一个路径压缩
                              }
                              void kruskal() {
                              	int cnt = 0;
                              	sort(e+1, e+m+1, cmp); // 排序所有的边
                              	for (int i = 1; i <= m; i++) { // 枚举所有的边
                              		int fx = dfs(e[i].x); // find
                              		int fy = dfs(e[i].y);
                              		if (fx != fy) { // 可以通过并查集函数来理解
                              			fa[fx] = fy; //
                              			ret += e[i].z;
                              			cnt++; // 这个没有用,但是这个可以计数是否可以构成最小生成树
                              		}
                              	}
                              	cout << ret;
                              }
                              
                              int main() {
                                  cin >> n >> m;
                              	INIT();
                                  for (int i = 1; i <= m; i++) {
                                  	scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
                              	}
                              	kruskal();
                                  return 0;
                              }
                              

                              并查集

                              • -2
                                @ 2023-8-10 12:54:55
                                #include<bits/stdc++.h>
                                using namespace std;
                                #define int long long
                                int m,n,cnt,sum;
                                int fa[100009];
                                struct edge{
                                    int w;
                                    int u,v;
                                };
                                edge e[200009];
                                bool cmp(edge x,edge y){
                                    return x.w<y.w;
                                }
                                void init(){
                                    cin>>n>>m;
                                    for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
                                    for(int i=1;i<=n;i++) fa[i]=i;
                                }
                                int anc(int k){
                                    if(fa[k]==k) return k;
                                    else return fa[k]=anc(fa[k]);
                                }
                                void relate(int x,int y){
                                    if(x<y) swap(x,y);
                                    fa[anc(y)]=anc(x);
                                }
                                signed main(){
                                    init();
                                    sort(e+1,e+m+1,cmp);
                                    for(int i=1;i<=m;i++){
                                        if(anc(e[i].u)!=anc(e[i].v)){
                                            cnt++;
                                            relate(e[i].u,e[i].v);
                                            sum+=e[i].w;
                                        }
                                        if(cnt==n-1) break;
                                    }
                                    if(cnt!=n-1) cout<<"No solution";
                                    else cout<<sum;
                                    return 0;
                                }
                                
                                • -2
                                  @ 2023-3-23 20:11:34
                                  #include<bits/stdc++.h>
                                  using namespace std;
                                  #define int long long
                                  int m,n,cnt,sum;
                                  int fa[100009];
                                  struct edge{
                                      int w;
                                      int u,v;
                                  };
                                  edge e[200009];
                                  bool cmp(edge x,edge y){
                                      return x.w<y.w;
                                  }
                                  void init(){
                                      cin>>n>>m;
                                      for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w;
                                      for(int i=1;i<=n;i++) fa[i]=i;
                                  }
                                  int anc(int k){
                                      if(fa[k]==k) return k;
                                      else return fa[k]=anc(fa[k]);
                                  }
                                  void relate(int x,int y){
                                      if(x<y) swap(x,y);
                                      fa[anc(y)]=anc(x);
                                  }
                                  signed main(){
                                      init();
                                      sort(e+1,e+m+1,cmp);
                                      for(int i=1;i<=m;i++){
                                          if(anc(e[i].u)!=anc(e[i].v)){
                                              cnt++;
                                              relate(e[i].u,e[i].v);
                                              sum+=e[i].w;
                                          }
                                          if(cnt==n-1) break;
                                      }
                                      if(cnt!=n-1) cout<<"No solution";
                                      else cout<<sum;
                                      return 0;
                                  }
                                  
                                  
                                  • -2
                                    @ 2022-3-16 16:25:22

                                    使用 Kruskal 算法。

                                    有环的情况可以用并查集跳过。

                                    #include<bits/stdc++.h>
                                    using namespace std;
                                    long long n,m,fa[100005],cnt,ans,s[100005];
                                    struct node{
                                    	long long u,v,w;
                                    }a[200005];
                                    bool cmp(node x,node y){
                                    	return x.w<y.w;
                                    }
                                    int find(int x){
                                    	if(fa[x]==x)
                                    		return x;
                                    	return fa[x]=find(fa[x]);
                                    }
                                    void merge(int x,int y){
                                    	if(s[x]<s[y])
                                    		swap(x,y);
                                    	int fx=find(x),fy=find(y);
                                    	fa[fy]=fx,s[fx]+=s[fy];
                                    }
                                    int main(){
                                    	scanf("%lld%lld",&n,&m);
                                    	for(int i=1;i<=m;i++)
                                    		scanf("%lld%lld%lld",&a[i].u,&a[i].v,&a[i].w);
                                    	sort(a+1,a+m+1,cmp);
                                    	for(int i=1;i<=n;i++)
                                    		fa[i]=i;
                                    	for(int i=1;i<=m;i++){
                                    		if(find(a[i].u)==find(a[i].v))
                                    			continue;
                                    		merge(a[i].u,a[i].v);
                                    		cnt++;
                                    		ans+=a[i].w;
                                    		if(cnt==n-1)
                                    			break;
                                    	}
                                    	printf("%lld",ans);
                                    	return 0;
                                    }
                                    
                                    • -5
                                      @ 2023-8-10 12:55:33

                                      #include<bits/stdc++.h> using namespace std; #define int long long int m,n,cnt,sum; int fa[100009]; struct edge{ int w; int u,v; }; edge e[200009]; bool cmp(edge x,edge y){ return x.w<y.w; } void init(){ cin>>n>>m; for(int i=1;i<=m;i++) cin>>e[i].u>>e[i].v>>e[i].w; for(int i=1;i<=n;i++) fa[i]=i; } int anc(int k){ if(fa[k]k) return k; else return fa[k]=anc(fa[k]); } void relate(int x,int y){ if(x<y) swap(x,y); fa[anc(y)]=anc(x); } signed main(){ init(); sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++){ if(anc(e[i].u)!=anc(e[i].v)){ cnt++; relate(e[i].u,e[i].v); sum+=e[i].w; } if(cntn-1) break; } if(cnt!=n-1) cout<<"No solution"; else cout<<sum; return 0; }

                                    • -5
                                      @ 2021-5-17 22:34:16

                                      注意:

                                      • 不要把洛谷AC代码移过来,注意数据范围
                                      • 不要用int!!

                                      不要复制下面的代码

                                      #include<bits/stdc++.h>
                                      using namespace std;
                                      int n,m;
                                      struct Edge{
                                      int u,v;
                                      long long len;
                                      }e[2000₁0];
                                      
                                      bool cmp(Edge a,Edge b){
                                      return a.len<=b.len;
                                      }
                                      int fa[100010];
                                      void init(){
                                      for(int i=1;i<=n;i++)fa[i]=i;
                                      }
                                      int get(int x){
                                      if(fa[x]==x)return x;
                                      return fa[x]=get(fa[x]);
                                      }
                                      void merge(int x,int y){
                                      x=get(x);
                                      y=get(y);
                                      if(x!=y){
                                      fa[x]=y;
                                      }
                                      }
                                      int kruskal(int n,int m){
                                      long long sum=0;
                                      init();
                                      sort(e,e+m,cmp);
                                      for(int i=0;i<m;i++){
                                      int fu=get(e[i].u);
                                      int fv=get(e[i].v);
                                      if(fu!=fv){
                                      fa[fv]=fu;
                                      sum+=e[i].len;
                                      }
                                      }
                                      return sum;
                                      }
                                      int mian(){
                                      cin>>n>>m;
                                      for(int i=0;i<m;++i)cin>>e[i].u>>e[i].v>>e[i].len;
                                      cout<<kruskal(n,m)<<endl;
                                      return 0;
                                      }
                                      
                                      • 1

                                      Information

                                      ID
                                      91
                                      Time
                                      1000ms
                                      Memory
                                      256MiB
                                      Difficulty
                                      3
                                      Tags
                                      # Submissions
                                      1135
                                      Accepted
                                      388
                                      Uploaded By