Codeforces 863F - Almost Permutation
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的更多相关文章
- [Codeforces 1208D]Restore Permutation (树状数组)
[Codeforces 1208D]Restore Permutation (树状数组) 题面 有一个长度为n的排列a.对于每个元素i,\(s_i\)表示\(\sum_{j=1,a_j<a_i} ...
- CodeForces 483C Diverse Permutation
Diverse Permutation Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64 ...
- codeforces 483C.Diverse Permutation 解题报告
题目链接:http://codeforces.com/problemset/problem/483/C 题目意思:给出 n 和 k,要求输出一个含有 n 个数的排列 p1, p2, ...,pn,使得 ...
- Codeforces 285C - Building Permutation
285C - Building Permutation 思路:贪心.因为每个数都不同且不超过n,而且长度也为n,所有排列只能为1 2 3 ......n.所以排好序后与对应元素的差值的绝对值加起来就是 ...
- codeforces C. Diverse Permutation
C. Diverse Permutation time limit per test 1 second memory limit per test 256 megabytes input standa ...
- CodeForces - 233A Perfect Permutation
A. Perfect Permutation time limit per test: 2 seconds memory limit per test: 256 megabytes input: st ...
- Codeforces 932.C Permutation Cycle
C. Permutation Cycle time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- 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 ...
- [Codeforces 482A] Diverse Permutation
[题目链接] https://codeforces.com/contest/482/problem/A [算法] 首先构造一个(k + 1)个数的序列 , 满足它们的差为1-k 对于i > k ...
随机推荐
- 洛谷P4592 [TJOI2018]异或 【可持久化trie树】
题目链接 BZOJ4592 题解 可持久化trie树裸题 写完就A了 #include<algorithm> #include<iostream> #include<cs ...
- JQuery队列queue与原生模仿其实现
jQuery中的queue和dequeue是一组很有用的方法,他们对于一系列需要按次序运行的函数特别有用.特别animate动画,ajax,以及timeout等需要一定时间的函数. queue() 方 ...
- 闲话JavaScript与Cookies
使用 Cookies 我们已经知道,在 document 对象中有一个 cookie 属性.但是 Cookie 又是什么?"某些 Web 站点在您的硬盘上用很小的文本文件存储了一些信息,这些 ...
- How do I see what character set a database / table / column is in MySQL?
Q: How do I see what the character set that a MySQL database, table and column are in? Is there some ...
- HDU4289:Control(最小割)
Control Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- MySQL主主搭建
1.在MySQL主从的基础上修改: #master1上 [mysqld] server-id=101 log-bin = mysql-bin auto-increment-increment = 2 ...
- 更改win10和mint双系统默认启动顺序
更改win7 & Linuxmint双系统安装后更改默认启动顺序 1.打开一个term,编辑/etc/default/grub,即sudo nano /etc/default/grub,把se ...
- x:Class, x:Key
x:Class: 用来创建一个partial的class, 比如默认生成的x:Class="MyTest.MainWindow", 会自动生成一个MainWindow的partia ...
- Java面向对象编程三大特性 --- 多态
多态特性: 子类Child继承父类Father,我们可以编写一个指向子类的父类类型引用,该引用既可以处理父类Father对象,也可以处理子类Child对象,当相同的消息发送给子类或者父类对象时,该对象 ...
- eclipse配置文件内存设置
1.-Xms64m -Xmx128m 2.配置文件的修改 http://wenku.baidu.com/link?url=spM-qCe0qHdhiykzwuzp-vBtcQrVtAzYiWe8uex ...