# LA7037-The Problem Needs 3D Arrays（最大稠密子图）

119人阅读 评论(0)

### 题目链接

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5049

### 思路

1. 新建源S和汇T，其中权值为正的结点，连一条S->该点的边，容量为该点权值。权值为负的结点，新建一条从该点->T的边，容量为该点权值的绝对值。
2. 对于原来的结点的边的关系，容量全部设为INF
3. 求该图的最小割
4. res = 权值为正的点的权值和 - 最小割

### 代码

#include <iostream>
#include <cstring>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <climits>
#include <deque>
#include <bitset>
#include <algorithm>
using namespace std;

#define PI acos(-1.0)
#define LL long long
#define PII pair<int, int>
#define PLL pair<LL, LL>
#define mp make_pair
#define IN freopen("in.txt", "r", stdin)
#define OUT freopen("out.txt", "wb", stdout)
#define scan(x) scanf("%d", &x)
#define scan2(x, y) scanf("%d%d", &x, &y)
#define scan3(x, y, z) scanf("%d%d%d", &x, &y, &z)
#define sqr(x) (x) * (x)
#define pr(x) cout << #x << " = " << x << endl
#define lc o << 1
#define rc o << 1 | 1
#define pl() cout << endl

const int maxn = 5000 + 500;
const double INF = 0x3e3e3e3e;
const double eps = 1e-8;
int n;
int a[105];

struct Edge {
int from, to;
double cap, flow;
Edge(int u, int v, double c, double f) : from(u), to(v), cap(c), flow(f) {

}
};

struct Dinic {
int n, m, s, t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int cur[maxn], d[maxn];

void init() {
for (int i = 0; i < maxn; i++) G[i].clear();
edges.clear();
}

void addedge(int u, int v, double c) {
edges.push_back(Edge(u, v, c, 0));
edges.push_back(Edge(v, u, 0, 0));
m = edges.size();
G[u].push_back(m - 2);
G[v].push_back(m - 1);
}

bool bfs() {
memset(vis, 0, sizeof(vis));
queue<int> Q;
Q.push(s);
vis[s] = 1, d[s] = 0;
while (!Q.empty()) {
int x = Q.front(); Q.pop();
int _s = G[x].size();
for (int i = 0; i < _s; i++) {
Edge &e = edges[G[x][i]];
if (!vis[e.to] && e.cap - e.flow > eps) {
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}

double dfs(int x, double a) {
if (x == t || a < eps) return a;
double flow = 0, f;
for (int &i = cur[x]; i < G[x].size(); i++) {
Edge &e = edges[G[x][i]];
if (d[e.to] == d[x] + 1) {
if (min(a, e.cap - e.flow) > eps) {
f = dfs(e.to, min(a, e.cap - e.flow));
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a <= eps) break;
}
}
}
return flow;
}

double max_flow(int s, int t) {
this->s = s;
this->t = t;
double flow = 0;
while (bfs()) {
memset(cur, 0, sizeof(cur));
flow += dfs(s, INF);
}
return flow;
}
};

Dinic D;
int tot, S, T;
void buildgraph() {
int offset = n * (n - 1) / 2 + n;
S = offset + 2;
T = offset + 3;
tot = n + 1;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (a[i] > a[j]) {
}
}
}
for (int i = 1; i <= n; i++) D.addedge(i, T, 0);
for (int i = n + 1; i < tot; i++) D.addedge(S, i, 1);
}

bool judge(double x) {
for (int v = 1; v <= n; v++) {
for (int i = 0; i < D.G[v].size(); i++) {
Edge &e = D.edges[D.G[v][i]];
if (e.to == T) e.cap = x;
}
}
for (int i = 0; i < D.edges.size(); i++) {
Edge &e = D.edges[i];
e.flow = 0;
}
double flow = D.max_flow(S, T);
double pov = double(tot - n - 1);
return (pov - flow) >= eps;
}

double solve() {
D.init();
buildgraph();
int m = tot - n - 1;
double L = 0, R = double(m), M = (L + R) / 2;
while (R - L > eps) {
M = (L + R) / 2.0;
if (judge(M)) L = M;
else R = M;
}
return M;
}

int main() {
int T, kase = 0;
scan(T);
while (T--) {
scan(n);
for (int i = 0; i < n; i++) scan(a[i]);
double res = solve();
printf("Case #%d: %.6lf\n", ++kase, res);
}
return 0;
}


0
0

【直播】机器学习&数据挖掘7周实训--韦玮
【套餐】系统集成项目管理工程师顺利通关--徐朋
【直播】3小时掌握Docker最佳实战-徐西宁
【套餐】机器学习系列套餐（算法+实战）--唐宇迪
【直播】计算机视觉原理及实战--屈教授
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之矩阵--黄博士
【套餐】微信订阅号+服务号Java版 v2.0--翟东平
【直播】机器学习之凸优化--马博士
【套餐】Javascript 设计模式实战--曾亮

* 以上用户言论只代表其个人观点，不代表CSDN网站的观点或立场
个人资料
• 访问：30147次
• 积分：2670
• 等级：
• 排名：第13521名
• 原创：254篇
• 转载：0篇
• 译文：0篇
• 评论：0条
友链
阅读排行