zoukankan      html  css  js  c++  java
  • UVALive 7037:The Problem Needs 3D Arrays(最大密度子图)

    题目链接

    题意

    给出n个点,每个点有一个值,现在要选择一些点的集合,使得(选择的点生成的逆序对数目)/(选择的点的数量)的比率最大。

    思路

    点与点之间生成一个逆序对可以看做是得到一个边,那么就是分数规划问题|E|/|V|,即求最大密度子图。

    先处理出所有的逆序对,然后把这些逆序对看作边。

    二分枚举 h(g) = |E| - g * |V|中的g,h(g)为递减函数,把g看做点权,转化为最大权闭合图处理,当 h(g) 为0时,得到最优解,这时候的g就是答案。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> pii;
    const int INF = 0x3f3f3f3f;
    const int N = 11111;
    const double eps = 1e-8;
    const double inf = 1000000000;
    struct Edge {
    	int u, v, nxt;
    	double cap;
    } edge[N*4];
    int S, T, n, m, a[N], head[N], tot, pre[N], cur[N], gap[N], dis[N];
    pii p[N];
    
    void Add(int u, int v, double cap) {
    	edge[tot] = (Edge) { u, v, head[u], cap }; head[u] = tot++;
    	edge[tot] = (Edge) { v, u, head[v], 0 }; head[v] = tot++;
    }
    
    void BFS(int T) {
    	memset(dis, INF, sizeof(dis));
    	memset(gap, 0, sizeof(gap));
    	queue<int> que;
    	que.push(T); dis[T] = 0; gap[0] = 1;
    	while(!que.empty()) {
    		int u = que.front(); que.pop();
    		for(int i = head[u]; ~i; i = edge[i].nxt) {
    			int v = edge[i].v;
    			if(dis[v] != INF) continue;
    			dis[v] = dis[u] + 1;
    			gap[dis[v]]++;
    			que.push(v);
    		}
    	}
    }
    
    double ISAP(int S, int T, int n) {
    	BFS(T);
    	memcpy(cur, head, sizeof(cur));
    	int u = pre[S] = S, i, index;
    	double ans = 0, flow;
    	while(dis[S] < n) {
    		if(u == T) {
    			flow = inf; index = u;
    			for(u = S; u != T; u = edge[cur[u]].v)
    				if(flow > edge[cur[u]].cap) flow = edge[cur[u]].cap, index = u;
    			for(u = S; u != T; u = edge[cur[u]].v)
    				edge[cur[u]].cap -= flow, edge[cur[u]^1].cap += flow;
    			ans += flow; u = index;
    		}
    		for(i = cur[u]; ~i; i = edge[i].nxt)
    			if(dis[edge[i].v] == dis[u] - 1 && edge[i].cap > 0) break;
    		if(~i) {
    			cur[u] = i; pre[edge[i].v] = u; u = edge[i].v;
    		} else {
    			if(--gap[dis[u]] == 0) break;
    			int md = n + 1;
    			for(i = head[u]; ~i; i = edge[i].nxt)
    				if(dis[edge[i].v] < md && edge[i].cap > 0)
    					cur[u] = i, md = dis[edge[i].v];
    			gap[dis[u] = md + 1]++;
    			u = pre[u];
    		}
    	}
    	return ans;
    }
    
    void Build(double g) {
    	memset(head, -1, sizeof(head)); tot = 0;
    	for(int i = 1; i <= n; i++) Add(i, T, g);
    	for(int i = 1; i <= m; i++) {
    		Add(S, i + n, 1);
    		Add(i + n, p[i].first, inf);
    		Add(i + n, p[i].second, inf);
    	}
    }
    
    int main() {
    	int t; scanf("%d", &t);
    	for(int cas = 1; cas <= t; cas++) {
    		scanf("%d", &n);
    		for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    		m = 0;
    		for(int i = 1; i <= n; i++)
    			for(int j = i + 1; j <= n; j++)
    				if(a[i] > a[j]) p[++m] = {i, j};
    		double l = 0, r = m + 1, now;
    		S = 0, T = n + m + 1;
    		while(r - l >= eps) {
    			double mid = (l + r) / 2;
    			Build(mid);
    			now = 1.0 * m - ISAP(S, T, T + 1);
    			if(now < eps) r = mid;
    			else l = mid;
    		}
    		printf("Case #%d: %.12f
    ", cas, l);
    	}
    	return 0;
    }
    
    /*
    1
    5
    3 4 2 5 1
    
    Case #1: 1.250000000000
    */
    
  • 相关阅读:
    access 导数据到sql server 2008
    axis2 调用.net基于https的WebService接口
    android layout 属性大全
    sqlite-manager
    android Permission 访问权限许可
    ImageSwitcher 右向左滑动的实现方式
    java 全角半角转换函数
    Delphi中使用Office中VBA的优缺点
    Delphi中控制VBA 宏
    Delphi 与 Word_VBA
  • 原文地址:https://www.cnblogs.com/fightfordream/p/7683838.html
Copyright © 2011-2022 走看看