zoukankan      html  css  js  c++  java
  • [BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树

    [BZOJ3080]Minimum Variance Spanning Tree/[BZOJ3754]Tree之最小方差树

    题目大意:

    给定一个(n(nle50))个点,(m(mle1000))条边的带权无向图,每条边的边权为(w_i(w_ile50))。求最小方差生成树。

    3080数据范围:(nle50,mle1000,w_ile50)
    3754数据范围:(nle100,mle1000,w_ile100)

    其中3754询问的是最小标准差。

    思路:

    由于(w_i)很小,因此我们可以枚举树上的边权和(sum w_i),以((w_i-ar w)^2)为新的边权做最小生成树。若最后树上的(sum w_i=)一开始枚举的值,那么就更新答案。

    源代码(3080):

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=51,M=1001;
    double d;
    inline double sqr(const double &x) {
    	return x*x;
    }
    struct Edge {
    	int u,v,w;
    	bool operator < (const Edge &rhs) const {
    		return sqr(w-d)<sqr(rhs.w-d);
    	}
    };
    Edge edge[M];
    class DisjointSet {
    	private:
    		int anc[N];
    		int find(const int &x) {
    			return x==anc[x]?x:anc[x]=find(anc[x]);
    		}
    	public:
    		void reset(const int &n) {
    			for(register int i=1;i<=n;i++) anc[i]=i;
    		}
    		void merge(const int &x,const int &y) {
    			anc[find(x)]=find(y);
    		}
    		bool same(const int &x,const int &y) {
    			return find(x)==find(y);
    		}
    };
    DisjointSet djs;
    int main() {
    	for(register int i=1;;i++) {
    		const int n=getint(),m=getint();
    		if(n==0&&m==0) return 0;
    		for(register int i=1;i<=m;i++) {
    			edge[i].u=getint();
    			edge[i].v=getint();
    			edge[i].w=getint();
    		}
    		d=0;
    		std::sort(&edge[1],&edge[m]+1);
    		int l=0,r=0;
    		for(register int i=1;i<n;i++) l+=edge[i].w;
    		for(register int i=m;i>m-n+1;i--) r+=edge[i].w;
    		double ans=1e18;
    		for(register int i=l;i<=r;i++) {
    			d=1.*i/(n-1);
    			std::sort(&edge[1],&edge[m]+1);
    			djs.reset(n);
    			int sum1=0;
    			double sum2=0;
    			for(register int i=1;i<=m;i++) {
    				const int &u=edge[i].u,&v=edge[i].v;
    				if(djs.same(u,v)) continue;
    				djs.merge(u,v);
    				sum1+=edge[i].w;
    				sum2+=sqr(edge[i].w-d);
    			}
    			if(sum1==i) {
    				ans=std::min(ans,sum2/(n-1));
    			}
    		}
    		printf("Case %d: %.2f
    ",i,ans);
    	}
    }
    

    源代码(3754):

    #include<cmath>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    inline int getint() {
    	register char ch;
    	while(!isdigit(ch=getchar()));
    	register int x=ch^'0';
    	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    	return x;
    }
    const int N=101,M=2001;
    double d;
    inline double sqr(const double &x) {
    	return x*x;
    }
    struct Edge {
    	int u,v,w;
    	bool operator < (const Edge &rhs) const {
    		return sqr(w-d)<sqr(rhs.w-d);
    	}
    };
    Edge edge[M];
    class DisjointSet {
    	private:
    		int anc[N];
    		int find(const int &x) {
    			return x==anc[x]?x:anc[x]=find(anc[x]);
    		}
    	public:
    		void reset(const int &n) {
    			for(register int i=1;i<=n;i++) anc[i]=i;
    		}
    		void merge(const int &x,const int &y) {
    			anc[find(x)]=find(y);
    		}
    		bool same(const int &x,const int &y) {
    			return find(x)==find(y);
    		}
    };
    DisjointSet djs;
    int main() {
    	const int n=getint(),m=getint();
    	for(register int i=1;i<=m;i++) {
    		edge[i].u=getint();
    		edge[i].v=getint();
    		edge[i].w=getint();
    	}
    	std::sort(&edge[1],&edge[m]+1);
    	int l=0,r=0;
    	for(register int i=1;i<n;i++) l+=edge[i].w;
    	for(register int i=m;i>m-n+1;i--) r+=edge[i].w;
    	double ans=1e18;
    	for(register int i=l;i<=r;i++) {
    		d=1.*i/(n-1);
    		std::sort(&edge[1],&edge[m]+1);
    		djs.reset(n);
    		int sum1=0;
    		double sum2=0;
    		for(register int i=1;i<=m;i++) {
    			const int &u=edge[i].u,&v=edge[i].v;
    			if(djs.same(u,v)) continue;
    			djs.merge(u,v);
    			sum1+=edge[i].w;
    			sum2+=sqr(edge[i].w-d);
    		}
    		if(sum1==i) {
    			ans=std::min(ans,sum2/(n-1));
    		}
    	}
    	printf("%.4f
    ",sqrt(ans));
    }
    
  • 相关阅读:
    WoSign全球可信网站安全认证签章安装指南
    软件测试学习(4)
    软件测试学习(3) 第一次上机实验
    软件测试学习(2)
    C#实验——Problem Statement
    C#实验——Supplementary Specifications
    python— if __name__=='__main__':的作用
    python--网络请求
    python--程序分目录、加环境变量
    python--接口开发
  • 原文地址:https://www.cnblogs.com/skylee03/p/9729368.html
Copyright © 2011-2022 走看看