zoukankan      html  css  js  c++  java
  • UVA 1395 苗条的生成树(最小生成树+并查集)

    苗条的生成树

    紫书P358 这题最后坑了我20分钟,怎么想都对了啊,为什么就wa了呢,最后才发现,是并查集的编号搞错了。
    题目编号从1开始,我并查集编号从0开始 = =
    图论这种题真的要记住啊!!题目大部分都是从1开始编号,而代码大部分是从0开始编号,所以要把输入减减。

    【题目链接】苗条的生成树

    【题目类型】最小生成树+并查集

    &题解:

    如果你看懂了Kruskal算法,那么这个也就很好懂了。
    首先按边排序,之后找个连续的区间[L,R] 判断是否已经是生成树,如果是,更新答案就好。
    判断是否为生成树这里有点意思:cnt=0 当合并并查集的时候,cnt++ 当cnt==n-1时,代表正好进入了n-1条边,所以就一定是生成树了。

    【时间复杂度】O((m^2))

    &代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int maxm = 5000 + 5 ;
    int n,m,u[maxm],v[maxm],w[maxm];
    int r[maxm],p[maxm];
    int cmp(int i,int j) {return w[i]<w[j];}
    int find(int x) {return p[x]==x?x:p[x]=find(p[x]);}
    void Solve()
    {
        while(cin>>n>>m){
        	if (n==0&&m==0) break;
        	for(int i=0;i<m;i++){
        		cin>>u[i]>>v[i]>>w[i];
        		u[i]--,v[i]--,w[i]--;
        	}
        	for(int i=0;i<m;i++)
        		r[i]=i;
        	sort(r,r+m,cmp);
        	int ans=INF;
        	for(int L=0;L<m;L++){
        		for(int i=0;i<n;i++)
        			p[i]=i;
        		int cnt=0,R;
        		for(R=0;L+R<m;R++){
        			int e=R+L;
        			int x=find(u[r[e]]),y=find(v[r[e]]);
        			if (x!=y){
        				cnt++;
        				p[x]=y;
        			}
        			if (cnt==n-1)
        				break;
        		}
        		if(cnt==n-1)
        			ans=min(ans,w[r[R+L]]-w[r[L]]);
        	}
        	if (ans!=INF) printf("%d
    ",ans);
    	    else puts("-1");
        }
    }
    int main()
    {
        Solve();
        return 0;
    }
    
  • 相关阅读:
    antd的form表单4.0
    antd的select搜索展现错误
    ts的枚举类型简化if else if判断
    深入解读webpack
    常用es6语法总结
    手动配置webpack
    apply,all,bind的区别
    面试题小结
    react中根据后台值动态配置
    react动态路由以及获取动态路由
  • 原文地址:https://www.cnblogs.com/s1124yy/p/6056501.html
Copyright © 2011-2022 走看看