17 条题解

  • 7
    @ 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;
    }
    
    • 3
      @ 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;
      }
      
      • 3
        @ 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
            @ 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;
            }
            • 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;
                }
                
                • 1
                  @ 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;
                  }
                  
                  • 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;
                    }
                    
                    • -1
                      @ 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;
                      }
                      

                      并查集

                      • -1
                        @ 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;
                        }
                        
                        • -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;
                          }
                          
                          • -1
                            @ 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;
                            }
                            

                            完结撒花!

                            • -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

                                  信息

                                  ID
                                  91
                                  时间
                                  1000ms
                                  内存
                                  256MiB
                                  难度
                                  3
                                  标签
                                  递交数
                                  955
                                  已通过
                                  322
                                  上传者