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. 高性能服务器开发之C++定时器

    高性能服务器开发之C++定时器 来源: https://www.cnblogs.com/junye/p/5836552.html 写这篇文章前搜了下网上类似的文章,有很多,所以笔者的这篇文章就不对定时 ...

  2. [Leetcode] Remove duplicates from sorted array ii 从已排序的数组中删除重复元素

    Follow up for "Remove Duplicates":What if duplicates are allowed at most twice? For exampl ...

  3. 洛谷 P3203 [HNOI2010]弹飞绵羊 解题报告

    P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...

  4. 兔子与兔子 [Hash]

    兔子与兔子 描述 很久很久以前,森林里住着一群兔子.有一天,兔子们想要研究自己的 DNA 序列.我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文字母) ...

  5. 跨域请求json数据

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. Linux下文件解压命令

    1.压缩命令: 命令格式:tar -zcvf 压缩文件名.tar.gz 被压缩文件名 可先切换到当前目录下.压缩文件名和被压缩文件名都可加入路径. 2.解压缩命令: 命令格式:tar -zxvf 压缩 ...

  7. 稀疏编码概率解释(基于1996年Olshausen与Field的理论 )

    一.Sparse Coding稀疏编码 稀疏编码算法是一种无监督学习方法,它用来寻找一组“超完备”基向量来更高效地表示样本数据.稀疏编码算法的目的就是找到一组基向量 ,使得我们能将输入向量 表示为这些 ...

  8. AE特效-与MAYA的结合、制作音乐舞蹈太极动作

    http://blog.sina.com.cn/s/blog_a439a2670101fbkk.html AE特效-与MAYA的结合.制作音乐舞蹈太极动作 (2013-07-24 14:44:12) ...

  9. Kuangbin 带你飞-线段树专题 题解

    HDU 1166 敌兵布阵 单调更新区间查询和 #include <map> #include <set> #include <list> #include < ...

  10. c#使用selenium截图,操作dom元素

    using System; //添加selenium的引用 using OpenQA.Selenium.PhantomJS; using OpenQA.Selenium.Chrome; using O ...