CF GYM 100548 The Problem Needs 3D Arrays(2014ACM西安现场赛Problem C)

ProblemC. The Problem Needs 3D Arrays

Description

A permutation is asequence of integers p1, p2, . . . , pn,consisting of n distinct positive integers and each of them does notexceed n. Assume that r(S) of sequence S denotes the
number ofinversions in sequence S (if i < j and Si > Sj,then the pair of (i, j) is called an inversion of S), l(S) ofsequence S denotes the length of sequence S. Given a permutation P oflength n, it’s your task to find a subsequence S
of P with maximumr(S) / l(S). A subsequence of P is a sequence (pi1, pi2,. . . , pit) which satisfies that 0 < i1 <i2 < . . . < it ≤ n.

Input

The first line ofthe input gives the number of test cases, T. T test cases follow.

For each test case,the first line contains an integer n (1 ≤ n ≤ 100), the length ofthe permutation P. The second line contains n integers p1,p2, . . . , pn, which represents thepermutation
P.

Output

For each test case,output one line containing “Case #x: y”, where x is the test casenumber (starting from 1) and y is the maximum r(S) / l(S).

Your answer will beconsidered correct if it is within an absolute error of 10?6of the correct answer.

Samples


Sample Input


Sample Output


1

5

3 4 2 5 1


Case #1: 1.250000000000

知识点:

最大密度子图、最大权闭合图、最小割。

题目大意:

给出1~n这n个正整数的一种排列P,要求在P中找出一个子序列S,使得子序列中包含的逆序数对数r(S)和子序列的长度l(S)的比值最大。输出这个最大的比值r(S)/
l(S)。

解题思路:


可以将每个数看成图中的点,将逆序对的关系转换为图中的边。即构成了一个无向图。样例可以转换为下图:

现在要求的就是在图中选取一些点,以及他们互相之间相连的边,构成一个闭合子图。使得图中的边数(逆序对数)与点数(选取的数字)的比值最大。这就是一个最大密度子图的模型。样例的最佳选取方案,就是选择图中红色标注的点和边,共4个点5条边,比值为1.25。

根据胡伯涛的论文《最小割模型在信息学竞赛中的应用》,可以使用0-1分数规划的模型。根据分数规划一般步骤,二分查找答案。对于一个答案的猜测值g,将原图转化为网络G(V,E)的过程,即在原图点集V的基础上增加源s和汇t;将每条原无向边替换为两条容量为1的有向边(u,v)和(v,u);增加连接源到原图每个点的有向边(s,v),容量为U;增加连接原图每个点v到汇t的有向边(v,t),容量为(U+2g?d[v])(其中d[v]是v点的度数)。求出网络的最小割(等于最大流),如果(U×n-最小割)/
2 >=0,则猜测值g是可行的,放大g,继续二分;若<0则是不可行的,缩小g,继续二分。最后得出的就是可行的最大的g。即可求出最大的比值。

参考代码:(未AC

#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#include <cmath>
using namespace std;

const double INF = 1 << 30;
const double EPS = 1e-12;
const int MAXN = 110;
const int MAXM = 50010;

struct Edge {
    int u, v, next;
    double c;
    Edge() {}
    Edge(int _u, int _v, double _c, int _next) : u(_u), v(_v), c(_c), next(_next) {}
} edge[MAXM];

int head[MAXN], cnt;
bool visited[MAXN];
int path[MAXN], d[MAXN], src, to;
int n, m, nCase, cCase, p[MAXN], degree[MAXN];
vector<pair<int, int> > E;

void addEdge(int u, int v, double c) {
    edge[cnt] = Edge(u, v, c, head[u]);
    head[u] = cnt++;
    edge[cnt] = Edge(v, u, 0, head[v]);
    head[v] = cnt++;
}

bool bfs() {
    memset(d, 0, sizeof(d));
    queue<int> q;
    q.push(src);
    d[src] = 1;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].v;
            if (edge[i].c && !d[v]) {
                d[v] = d[u] + 1;
                q.push(v);
            }
        }
    }
    return d[to];
}

double dfs(int x, double pf) {
    if (x == to) return pf;
    double ret = 0;
    for (int i = head[x]; i != -1 && pf; i = edge[i].next) {
        int v = edge[i].v;
        if (edge[i].c && d[v] == d[x] + 1) {
            double p = dfs(v, min(edge[i].c, pf));
            edge[i].c -= p;
            edge[i ^ 1].c += p;
            ret += p;
            pf -= p;
        }
    }
    if (!ret) d[x] = -2;
    return ret;
}

double dinic() {
    double ret = 0.0;
    while (bfs()) ret += dfs(src, INF);
    return ret;
}

inline void buildEdge(double g) {
    memset(head, -1, sizeof(head));
    cnt = 0;

    src = 0;
    to = n + 1;

    for (int i = 0; i < m; i++) {
        addEdge(E[i].first, E[i].second, 1.0);
        addEdge(E[i].second, E[i].first, 1.0);
    }
    for (int i = 1; i <= n; i++) {
        addEdge(src, i, m * 1.0);
        addEdge(i, to, m * 1.0 + 2.0 * g - degree[i]);
    }
}

void init() {
    E.clear();
    memset(degree, 0, sizeof(degree));
}

void input() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", &p[i]);
    }
}

inline bool check(double g) {
    buildEdge(g);
    double h = (1.0 * m * n - dinic()) / 2.0;
    return h > 0;
}

void solve() {
    for (int i = 1; i <= n; i++) {
        for (int j = i+1; j <= n; j++) {
            if (p[i] > p[j]) {
                E.push_back(make_pair(i, j));
                degree[i]++;
                degree[j]++;
            }
        }
    }
    m = E.size();

    if (m == 0) {
        printf("Case #%d: %.12lf\n", ++cCase, 0);
        return;
    }

    double l = 1.0 / n - EPS, r = m * 1.0 + EPS;
    while (r - l > EPS) {
        double mid = (l + r) / 2.0;
        if (check(mid)) {
            l = mid;
        } else {
            r = mid;
        }
    }

    printf("Case #%d: %.12lf\n", ++cCase, l);
}

int main() {
    scanf("%d", &nCase);
    while (nCase--) {
        init();
        input();
        solve();
    }
    return 0;
}

欢迎讨论指正。

时间: 2024-10-13 16:14:56

CF GYM 100548 The Problem Needs 3D Arrays(2014ACM西安现场赛Problem C)的相关文章

CF GYM 100548 Built with Qinghuai and Ari Factor(2014ACM西安现场赛Problem A)

ProblemA. Built with Qinghuai and Ari Factor Description DISCLAIMER: Allnames, incidents, characters and places appearing in this problem arefictitious. Any resemblance to actual events or locales or realpersons, living or dead, is purely coincidenta

CF GYM 100548 The Problem to Make You Happy(2014ACM西安现场赛Problem H)

ProblemH. The Problem to Make You Happy Description Alice and Bob aregood friends, as in every other storyline. One day Alice and Bob areplaying an interesting game. The game is played on a directedgraph with n vertices and m edges, Alice and Bob hav

CF GYM 100548 Last Defence(2014ACM西安现场赛Problem K)

ProblemK. Last Defence Description Given two integersA and B. Sequence S is defined as follow: ? S0 = A ? S1 = B ? Si = |Si?1 ?Si?2| for i ≥ 2 Count the number ofdistinct numbers in S. Input The first line ofthe input gives the number of test cases,

CF GYM 100548 Color(2014ACM西安现场赛Problem F)

ProblemF. Color Description Recently, Mr. Bigrecieved n flowers from his fans. He wants to recolor those flowerswith m colors. The flowers are put in a line. It is not allowed tocolor any adjacent flowers with the same color. Flowers i and i + 1are s

Gym - 100548C The Problem Needs 3D Arrays

Problem C.   The Problem Needs 3D Arrays Time Limit: 6000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u Description A permutation is a sequence of integers p1,p2,...,pn, consisting of n distinct positive integers and each of them does not e

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

题意:给一段子序列,定义密度:子序列中的逆序对数/子序列的长度 求这个序列的对大密度. 分析:将序列中的每个位置视作点,逆序对\(<i,j>\)之间表示点i与点j之间有一条无向边.所以就转化为了最大密度子图的模型. #include<bits/stdc++.h> using namespace std; #define eps 1e-7 #define INF 0x3f3f3f3f const int MAXN=1010;//点数的最大值 const int MAXM=400010

CF gym 101933 K King&#39;s Colors —— 二项式反演

题目:http://codeforces.com/gym/101933/problem/K 其实每个点的颜色只要和父亲不一样即可: 所以至多 i 种颜色就是 \( i * (i-1)^{n-1} \),设为 \( f(i) \),设恰好 i 种颜色为 \( g(i) \) 那么 \( f(i) = \sum\limits_{j=0}^{i} C_{i}^{j} * g(j) \) 二项式反演得到 \( g(i) = \sum\limits_{j=0}^{k} (-1)^{k-j} * C_{k}

CF Gym 101955G Best ACMer Solves the Hardest Problem

链接:https://codeforces.com/gym/101955/problem/G 题意:在二维平面上四种操作: 1,加一个带权的点: 2,删去一个点: 3,给一个点周围欧几里得距离为sqrt(k)的存在的点点权都加w: 4,查询一个到点欧几里得距离为sqrtk的点权和. x, y<6000, k<1e7, sigma(询问次数)<1e6,time:12s 题解:原本以为是数据结构,发现距离为k的x,y其实不多,直接存vector<pii>dis[maxk]暴力即可

Gym 101194C / UVALive 7899 - Mr. Panda and Strips - [set][2016 EC-Final Problem C]

题目链接: http://codeforces.com/gym/101194/attachments https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5921 题意: 一个长度为 $N$ 的序列,要求选出两段不重叠的区间,要求两个区间包含的元素均互不相同,求两段区间的长度和最大为多少. 题解: (主要参考https://blo