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. [NOIP2017 TG D2T2]宝藏

    题目大意:给定一个有重边,边有权值的无向图.从某一个点出发,求到达所有的点需要的最少费用,并且限制两点之间只有一条路径.费用的计算公式为:所有边的费用之和.而边$x->y$的费用就为:$y$到初 ...

  2. requestAnimationFrame实现一帧的函数节流

    用一个变量判断raf的回调是否已经执行了,已经执行了说明过了一帧,通常是16.7ms,达到了函数节流一帧的目的. var locked = false; window.addEventListense ...

  3. 【bzoj3224】Tyvj 1728 普通平衡树 01Trie姿势+平衡树的四种姿势 :splay,旋转Treap,非旋转Treap,替罪羊树

    直接上代码 正所谓 人傻自带大常数 平衡树的几种姿势:  AVL Red&Black_Tree 码量爆炸,不常用:SBT 出于各种原因,不常用. 常用: Treap 旋转 基于旋转操作和随机数 ...

  4. input checkbox 多选 验证

    # input checkbox 多选 验证``` <ul class="orderMsg_radio"> <!--单选--> <input valu ...

  5. Python基础(6)_函数

    一 为何要有函数? 不加区分地将所有功能的代码垒到一起,问题是: 代码可读性差 代码冗余 代码可扩展差 如何解决? 函数即工具,事先准备工具的过程是定义函数,拿来就用指的就是函数调用 结论:函数使用必 ...

  6. 在Idea中使用Eclipse编译器

    Eclipse编译器对Javac编译器的优点如下: 1.Proceed on errors 如果使用Javac编译器,你除了在执行之前修复所有错误之外没有其它的选择.然而Eclipse编译器却可以不管 ...

  7. bzoj 1088 DP

    我们可以用w[i][s]来表示到第i位的方案,s代表第i位和第i+1位是否有雷的二进制串,那么我们就可以根据每一位的雷的数量转移了. /******************************** ...

  8. hdu 2544 最短路 (dijkstra,floyd)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544 题目大意:找到两点间最短的距离值. 代码一:(dijkstra算法) #include < ...

  9. C++学习笔记之——内联函数,引用

    本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和http://www.cnblogs.com/xujianqing/ 作者:晨凫 ...

  10. Django-Form 补充

    一.Form的前端循环 class LoginForm(Form): name = ... pwd = ... def func(request): form = LoginForm() return ...