首页 > 其他 > 详细

Codeforces Round #250 (Div. 1) B 并查集

时间:2014-08-18 16:28:42      阅读:285      评论:0      收藏:0      [点我收藏+]

坑!神坑!深坑!,WA了几十把,最终答案  (ans * 2)/(n * 1.0 * (n - 1)) 要是写成(ans * 2)/(n *(n - 1)*1.0)就是WA,不明白为啥,愤怒的我 全改成double就可以了,若前面变量用了int的 答案必须是前一种写法,

题目不是特别难,没啥思路画一画就有思路了,10^5的n去扫肯定是要超时的,那就想想一次性的10^5,发想通过m是可以的,建边,边权就是两端点中小的那个,然后对最终答案的种数进行分析,发现其实就是 每次你要连接的两块连通块的个数相乘就是最终你包含的这些边要走的次数,这样求和,最终答案再乘以2就好了,题目下面的hint其实那个 个数乘以2貌似有些暴露,


int n,m;

int nnum[100005 + 55];

int fa[100005 + 55];

int sum[100005 + 55];

typedef struct Node {
	int fro,to,nex;
	int val;
	Node(int a = 0,int b = 0,int c = 0):fro(a),to(b),val(c){}
};

Node edge[100005 + 55];

void init() {
	memset(nnum,0,sizeof(nnum));
	memset(edge,0,sizeof(edge));
	for(int i=0;i<100005;i++)fa[i] = i;
	for(int i=0;i<100005;i++)sum[i] = 1;
}

bool input() {
	while(scanf("%d %d",&n,&m) == 2) {
		for(int i=1;i<=n;i++)scanf("%d",&nnum[i]);
		int q = m;
		int cnt = 0;
		for(int i=0;i<m;i++) {
			int u,v;
			scanf("%d %d",&u,&v);
			edge[i] = Node(u,v,min(nnum[u],nnum[v]));
		}
		return false;
	}
	return true;
}

bool cmp(Node x,Node y) {
	return x.val > y.val;
}

int find(int x) {
	if(fa[x] != x)fa[x] = find(fa[x]);
	return fa[x];
}

void cal() {
	sort(edge,edge + m,cmp);
	double ans = 0;
	for(int i=0;i<m;i++) {
		int dx = find(edge[i].fro);
		int dy = find(edge[i].to);
		if(dx != dy) {
			ans += (double)edge[i].val * sum[dx] * sum[dy];
			fa[dx] = dy;
			sum[dy] += sum[dx];
		}
	}
	printf("%.6lf\n",(ans * 2)/(n * 1.0 * (n - 1)));
}

void output() {

}

int main () {
	while(true) {
		init();
		if(input())return 0;
		cal();
		output();
	}
	return 0;
}


Codeforces Round #250 (Div. 1) B 并查集,布布扣,bubuko.com

Codeforces Round #250 (Div. 1) B 并查集

原文:http://blog.csdn.net/yitiaodacaidog/article/details/38660799

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!