863F - Almost Permutation

题意

给出每个位置可以放的数字的范围,定义 \(cost = \sum_{i=1}^{n}(cnt(i))^2\) ,其中 \(cnt(i)\) 为数字 \(i\) \((1 \leq i \leq n)\) 出现的次数。将每个位置都填上一个数字,求 \(cost\) 的最小值。

分析

没想到可以用网络流去解决这道问题。本题属于最小费用最大流问题。

对于每个代表数字的结点,从源点都要连 \(n\) 条边,费用为\(1,\ 3,\ 5,...,\ 2*k-1\),前缀和正好对应某个数字取 \(k\) 次时的花费。根据位置和可以放的数字之间的对应关系连边,费用为 \(0\) ,所有代表位置的结点连边到汇点,费用为 \(0\)。以上每条边的容量都为 \(1\) 。跑一下费用流的模板即可。

思维好题啊。

code

#include<bits/stdc++.h>
#define l first
#define r second
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int MAXN = 1005; //
const int MAXM = 10005; // 注意扩张的边的数量
const int INF = 0x3f3f3f3f;
struct Edge {
int to, next, cap, flow, cost;
} edge[MAXM * 4];
int head[MAXN], tol;
int pre[MAXN], dis[MAXN];
bool vis[MAXN];
int N;//节点总个数,节点编号从0~N-1
void init(int n) {
N = n;
tol = 0;
memset(head, -1, sizeof head);
memset(pre, 0, sizeof pre);
memset(dis, 0, sizeof dis);
memset(vis, 0, sizeof vis);
memset(edge, 0, sizeof edge);
}
void addedge (int u, int v, int cap, int cost) {
edge[tol] = Edge{v, head[u], cap, 0, cost};
head[u] = tol++;
edge[tol] = Edge{u, head[v], 0, 0, -cost};
head[v] = tol++;
}
bool spfa(int s, int t) {
queue<int>q;
for(int i = 0; i < N; i++) {
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0;
vis[s] = true;
q.push(s);
while(!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i].next) {
int v = edge[i]. to;
if(edge[i].cap > edge[i].flow &&
dis[v] > dis[u] + edge[i].cost) {
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if(!vis[v]) {
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t] == -1) return false;
else return true;
}
//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s, int t, int &cost) {
int flow = 0;
cost = 0;
while(spfa(s,t)) {
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
if(Min > edge[i].cap - edge[i]. flow)
Min = edge[i].cap - edge[i].flow;
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to]) {
edge[i].flow += Min;
edge[i^1].flow -= Min;
cost += edge[i].cost * Min;
}
flow += Min;
}
return flow;
}
P a[110];
int main() {
int n, q;
cin >> n >> q;
for(int i = 1; i <= n; i++) {
a[i].l = 1;
a[i].r = n;
}
int flg = 0;
while(q--) {
int op, l, r, v;
cin >> op >> l >> r >> v;
for(int i = l; i <= r; i++) {
if(op == 1) {
a[i].l = max(a[i].l, v);
} else {
a[i].r = min(a[i].r, v);
}
if(a[i].l > a[i].r) {
flg = 1;
break;
}
}
}
init(2 * n + 2);
int s = 0, t = 2 * n + 1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) { // 源点向每个代表数字的结点连 n 条边
addedge(s, i, 1, 1 + 2 * (j - 1));
}
for(int j = a[i].l; j <= a[i].r; j++) { // 根据数字和位置的对应关系连边
addedge(j, i + n, 1, 0);
}
addedge(i + n, t, 1, 0); // 代表位置的结点向汇点连边
}
int cost = 0;
int flow = minCostMaxflow(s, t, cost);
if(flow != n) cost = -1;
cout << cost << endl;
}

Codeforces 863F - Almost Permutation的更多相关文章

  1. [Codeforces 1208D]Restore Permutation (树状数组)

    [Codeforces 1208D]Restore Permutation (树状数组) 题面 有一个长度为n的排列a.对于每个元素i,\(s_i\)表示\(\sum_{j=1,a_j<a_i} ...

  2. CodeForces 483C Diverse Permutation

    Diverse Permutation Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64 ...

  3. codeforces 483C.Diverse Permutation 解题报告

    题目链接:http://codeforces.com/problemset/problem/483/C 题目意思:给出 n 和 k,要求输出一个含有 n 个数的排列 p1, p2, ...,pn,使得 ...

  4. Codeforces 285C - Building Permutation

    285C - Building Permutation 思路:贪心.因为每个数都不同且不超过n,而且长度也为n,所有排列只能为1 2 3 ......n.所以排好序后与对应元素的差值的绝对值加起来就是 ...

  5. codeforces C. Diverse Permutation

    C. Diverse Permutation time limit per test 1 second memory limit per test 256 megabytes input standa ...

  6. CodeForces - 233A Perfect Permutation

    A. Perfect Permutation time limit per test: 2 seconds memory limit per test: 256 megabytes input: st ...

  7. Codeforces 932.C Permutation Cycle

    C. Permutation Cycle time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. Codeforces 932 C.Permutation Cycle-数学 (ICM Technex 2018 and Codeforces Round #463 (Div. 1 + Div. 2, combined))

    C. Permutation Cycle   time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  9. [Codeforces 482A] Diverse Permutation

    [题目链接] https://codeforces.com/contest/482/problem/A [算法] 首先构造一个(k + 1)个数的序列 , 满足它们的差为1-k 对于i > k ...

随机推荐

  1. Linux SNMP 监控一些常用OID

    Linux SNMP 监控一些常用OID ===============linux服务器snmp常用oid http://www.haiyun.me/archives/linux-snmp-oid.h ...

  2. [洛谷P2210]Haywire

    题目大意:有$n(n\leqslant12)$个数,每个数和其他三个数连边,求一个排列,使得边的长度最小 题解:状压$DP$,$f_{i,j}$表示当前确定的数状态为$i$,有$j$条边起点被确定终点 ...

  3. 用JavaScript写一个类似PHP print_r的函数

    PHP print_r的函数很好用,可以用来打印数组.对象等的结构与数据,可惜JavaScript并没有原生提供类似的函数.不过我们可以试着自己来实现这个函数,下面提供一些方法与思路. 方法一 fun ...

  4. CVPR2014 Objectness 源码转换(完整版) VS2012 X64 –>win32

    一.版本转换  1.将源码中vs2012 X64版本转换为vs2012 win32版本. 2.源码下载及其相关资料下载http://mmcheng.net/zh/bing/ 3.需要下载源码(Pape ...

  5. Spring源码解析-AutowiredAnnotationBeanPostProcessor

    1.实现了BeanPostProcessor接口,可先看这个接口 ApplicationContext可以在自动检测BeanPostProcessor bean,在它创建完后可以创建任何的bean. ...

  6. Codeforces Round #348 (VK Cup 2016 Round 2, Div. 2 Edition) D

    D. Little Artem and Dance time limit per test 2 seconds memory limit per test 256 megabytes input st ...

  7. (转)Django常用命令

    转自GoodSpeed,http://www.cnblogs.com/cacique/archive/2012/09/30/2709145.html . . . . .

  8. 【Foreign】字符串匹配 [KMP]

    字符串匹配 Time Limit: 10 Sec  Memory Limit: 256 MB Description Input Output Sample Input 3 3 6 3 1 2 1 2 ...

  9. 关于might_sleep的一点说明---CONFIG_DEBUG_ATOMIC_SLEEP【转】

    转自:http://blog.chinaunix.net/uid-23769728-id-3157536.html 这个函数我在看代码时基本上是直接忽略的(因为我知道它实际上不干什么事),不过因为内核 ...

  10. (十四)git操作

    https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000