题目链接

题意

给出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\n", cas, l);
}
return 0;
} /*
1
5
3 4 2 5 1 Case #1: 1.250000000000
*/

UVALive 7037:The Problem Needs 3D Arrays(最大密度子图)的更多相关文章

  1. Uvalive 7037 The Problem Needs 3D Arrays(最大密度子图)

    题意:给一段子序列,定义密度:子序列中的逆序对数/子序列的长度 求这个序列的对大密度. 分析:将序列中的每个位置视作点,逆序对\(<i,j>\)之间表示点i与点j之间有一条无向边.所以就转 ...

  2. Gym - 100548C The Problem Needs 3D Arrays

    Problem C.   The Problem Needs 3D Arrays Time Limit: 6000MS Memory Limit: 262144KB 64bit IO Format: ...

  3. 2014 西安 The Problem Needs 3D Arrays

    The Problem Needs 3D Arrays 题意:给你n个数, 然后1-n的数, 然后要求按顺序选出m个数, 求 逆序数/m 个数的 最大值是多少. 题解:裸的最大密度子图.逆序的2个数建 ...

  4. Gym - 100548C The Problem Needs 3D Arrays (最大密度子图)

    TK在大多数 Unix平台.Windows平台和Macintosh系统都是预装好的,TKinter 模块是 Tk GUI 套件的标准Python接口.可实现Python的GUI编程. Tkinter模 ...

  5. 14西安区域赛C - The Problem Needs 3D Arrays

    最大密度子图裸题,详情请见胡博涛论文: https://wenku.baidu.com/view/986baf00b52acfc789ebc9a9.html 不加当前弧优化t到死= = //#prag ...

  6. POJ 3155 Hard Life 最大密度子图 最大权闭合图 网络流 二分

    http://poj.org/problem?id=3155 最大密度子图和最大权闭合图性质很相近(大概可以这么说吧),一个是取最多的边一个是取最多有正贡献的点,而且都是有选一种必须选另一种的限制,一 ...

  7. POJ 3155 Hard Life(最大密度子图)

    裸题.输入一个无向图,输出最大密度子图(输出子图结点数和升序编号). 看了<最小割模型在信息学竞赛中的应用——胡伯涛>的一部分,感觉01分数规划问题又是个大坑.暂时还看不懂. 参考http ...

  8. poj 3155 最大密度子图

    思路: 这个还是看的胡伯涛的论文<最小割在信息学竞赛中的应用>.是将最大密度子图问题转化为了01分数规划和最小割问题. 直接上代码: #include <iostream> # ...

  9. POJ3155 Hard Life [最大密度子图]

      题意:最大密度子图 #include<iostream> #include<cstdio> #include<cstring> #include<algo ...

随机推荐

  1. Ubuntu更改 resolv.conf 重启失效

    更改Ubuntu的 resolv.conf的时候,重启的时候,经常又给重置了.google大法找到方法. sudo apt-get install resolvconf  原来Ubuntu的resol ...

  2. openFrameworks 是一个旨在助力你进行开创性工作的开源 C++ 工具箱(是很多其它类库的组合)

    openFrameworks 是一个旨在助力你进行开创性工作的开源 C++ 工具箱,提供了简单且直观的实验框架.该工具箱具有常见的工具,并集合了众多常见的库: OpenGL, GLEW, GLUT,  ...

  3. 备份一个支持虚拟化的wrappanel

    public class VirtualizingWrapPanel : VirtualizingPanel, IScrollInfo { #region Fields UIElementCollec ...

  4. 使用tratto进行CISCO网络设备的管理

    测试环境: CSR1000V CentOS7.4 X64 Step 1:在CentOS7上安装python 3.0环境 [root@docker ~]# python3 -VPython 3.7.0[ ...

  5. Windows 10开发基础——指针事件和操作事件(一)

    主要内容: 1.指针事件 2.操作事件 1.指针事件 指针事件由各种活动输入源引发,包括触摸.触摸板.笔和鼠标(它们替代传统的鼠标事件).指针事件基于单一输入点(手指.笔尖.鼠标光标),但不支持基于速 ...

  6. Android零基础入门第66节:RecyclerView点击事件处理

    前面两期学习了RecyclerView的简单使用,并为其item添加了分割线.在实际运用中,无论是List还是Grid效果,基本都会伴随着一些点击操作,那么本期就来一起学习RecyclerView的点 ...

  7. 【Qt】一劳永逸解决UAC问题(修改mkspecs\win32-msvc2012\qmake.conf)

    如果你的程序跑在一个开启了UAC保护的系统中,而你的程序又没有"盾牌"的话,程序总是会受到各种阻挠的,比如读写文件,写注册表等. 有了"盾牌"的话就不会出现一些 ...

  8. 主要C++流派,看看你是哪一流

    1. 经典C++流:类是核心,例程多用C Runtime的,很少用模版,一般是正统教育的结果.2. 古典C流:基本上当C用,偶尔用用对象,不使用异常,喜欢怀旧.3. MFC流:秉承MFC的风格,主要使 ...

  9. 深入探索ScrollWindow

    最近做WIN32 API开发时发现对ScrollWindow的一些工作原理并不是太清楚,于是做了相关研究,记载下来和大家共同学习. 首先在WM_CREATE中获取系统字符的宽度和高度 case WM_ ...

  10. C#WinForm线程基类

    在CS模式开发中一般我们需要用到大量的线程来处理比较耗时的操作,以防止界面假死带来不好的体验效果,下面我将我定义的线程基类给大家参考下,如有问题欢迎指正. 基类代码 #region 方法有返回值 // ...