码迷,mamicode.com
首页 > 其他好文 > 详细

bnu 51644 Whalyzh's Problem(网络流,最大密度图) (北师16校赛)

时间:2016-04-29 16:28:34      阅读:186      评论:0      收藏:0      [点我收藏+]

标签:

很久以前,当whalyzh同学是一个萌新的时候,遇到了这么一个问题:

给定长为技术分享的序列技术分享,构造一个只有0和1的长为技术分享的序列技术分享,使得技术分享的值最大。

小Q同学想了一秒钟之后说:这不是一眼题么?然后whalyzh同学瞬间就会了。

过了几天,当whalyzh同学还是一个萌新的时候,遇到了这么一个问题:

给定技术分享阶方阵技术分享,构造一个只有0和1的技术分享的向量技术分享,使得技术分享的值最大。

小Q同学想了一分钟之后说:这不是一眼题么?然后whalyzh同学瞬间就会了。

又过了几天,当whalyzh仍然是一个萌新的时候,遇到了这么一个问题:

给定技术分享阶方阵技术分享,构造一个只有0和1的技术分享的向量技术分享,使得技术分享的值最大。

小Q同学想了一小时之后说:不能总是问我,你得自己去思考。然后whalyzh同学瞬间就懵逼了。

即使到现在,whalyzh同学仍然百思不得其解,希望你能帮他解决这个问题。

请注意,在这个问题中,规定技术分享

Input

第一行是一个正整数技术分享,表示测试数据的组数,

对于每组测试数据,

第一行是一个整数技术分享,表示方阵的大小,

接下来技术分享行,每行技术分享个整数技术分享,表示方阵中的数。

Output

对于每组测试数据,输出所求的最大值,答案精确到小数点后五位。

Sample Input

1
3
0 1 0
1 2 4
1 3 2

Sample Output

3.50000

Hint

对于样例,令技术分享,可取得最大值技术分享

Source

Author

hwq1352249

题目大意:

       给出一个矩阵B(元素小于等于10)和一个由01组成的向量A,能选择其中的B[i][j]当且仅当A[i]=A[j]=1且i!=j,给定B通过A中把一些数置为1来选择B中的数使得B中数的和比上A中1的个数最大。

解题思路:

       原问题等价于给定一个n个顶点的图,每两点之间有一条边,边权为1到10,然后从中选出一些点,使的这些点的诱导子图的边权和/点数尽可能大,这是一个最大密度子图问题。

感谢chitanda的代码~



#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 100
const double eps = 1e-8;
const double inf = 1e+8;
struct Edge { int v; double w; Edge *x; } *e, *lnk[N * N + 9], E[12 * N * N + 9];
int TT, S, T, n, m, b[N + 9][N + 9];
int g[N * N + 9], h[N * N + 9];

int dcmp(double x) {
	return (x > +eps) - (x < -eps);
}

void add(int u, int v, double w) {
	e->v = v, e->w = w, e->x = lnk[u], lnk[u] = e++;
	e->v = u, e->w = 0, e->x = lnk[v], lnk[v] = e++;
}

double sap(int u, double flw) {
	if (u == T) return flw;
	double det, sum = .0;
	for (Edge *p = lnk[u]; p; p = p->x)
		if (h[u] == h[p->v] + 1 && dcmp(p->w)) {
			det = sap(p->v, min(p->w, flw - sum));
			p->w -= det;
			E[(p - E) ^ 1].w += det;
			if (dcmp((sum += det) - flw) == 0) return sum;
		}
	if (h[S] >= m) return sum;
	if (--g[h[u]] == 0) h[S] = m;
	++g[++h[u]];
	return sum;
}

bool check(double x) {
	m = n + n * (n - 1) / 2;
	S = ++m, T = ++m;

	e = E;
	for (int i = 1; i <= m; ++i) lnk[i] = 0;
	for (int i = 1; i <= n; ++i) add(i, T, x);

	int cnt = n;
	double sum = .0;
	for (int i = 1; i < n; ++i)
		for (int j = i + 1; j <= n; ++j) {
			++cnt;
			if (b[i][j]) {
				sum += b[i][j];
				add(S, cnt, b[i][j]);
			}
			add(cnt, i, inf);
			add(cnt, j, inf);
		}
	g[0] = m;
	for (int i = 1; i <= m; ++i) g[i] = h[i] = 0;
	while (h[S] < m) sum -= sap(S, inf);
	return sum > eps;
}

int main() {
	scanf("%d", &TT);
	while (TT--) {
		scanf("%d", &n);
		memset(b, 0, sizeof b);
		for (int i = 1; i <= n; ++i)
			for (int j = 1; j <= n; ++j) 
			{
				int x;
				scanf("%d", &x);
				if (i < j) b[i][j] += x;
				if (i > j) b[j][i] += x;
			}
		double l = 0, r = 1000, m;
		while (fabs(r - l) > eps) 
		{
			m = (l + r) / 2;
			if (check(m)) l = m;
			else r = m;
		}
		printf("%.5f\n", l);
	}
	return 0;
}


bnu 51644 Whalyzh's Problem(网络流,最大密度图) (北师16校赛)

标签:

原文地址:http://blog.csdn.net/chat_c/article/details/51263578

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!