CF818G Four Melodies
题目描述
Author note: I think some of you might remember the problem “Two Melodies” from Eductational Codeforces Round 22. Now it’s time to make it a bit more difficult!
Alice is a composer, and recently she had recorded two tracks that became very popular. Now she has got a lot of fans who are waiting for new tracks.
This time Alice wants to form four melodies for her tracks.
Alice has a sheet with
�
n notes written on it. She wants to take four such non-empty non-intersecting subsequences that all of them form a melody and sum of their lengths is maximal.
Subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.
Subsequence forms a melody when each two adjacent notes either differ by 1 or are congruent modulo 7.
You should write a program which will calculate maximum sum of lengths of such four non-empty non-intersecting subsequences that all of them form a melody.
输入格式
The first line contains one integer number
�
n (
4
<
=
�
<
=
3000
4<=n<=3000 ).
The second line contains
�
n integer numbers
�
1
,
�
2
,
.
.
.
,
�
�
a
1
,a
2
,...,a
n
(
1
<
=
�
�
<
=
10
5
1<=a
i
<=10
5
) — notes written on a sheet.
输出格式
Print maximum sum of lengths of such four non-empty non-intersecting subsequences that all of them form a melody.
输入输出样例 #1
输入 #1
5
1 3 5 7 9
输出 #1
4
输入输出样例 #2
输入 #2
5
1 3 5 7 2
输出 #2
5
说明/提示
In the first example it is possible to compose
4
4 melodies by choosing any
4
4 notes (and each melody will consist of only one note).
In the second example it is possible to compose one melody with
2
2 notes —
1
,
2
1,2 . Remaining notes are used in other three melodies (one note per each melody).
代码:
C++
#include <bits/stdc++.h>
using namespace std;
class MinCostMaxFlow {
public:
MinCostMaxFlow(int n, int s, int t)
: n(n), s(s), t(t) {
head.assign(n + 1, -1);
}
void add_edge(int u, int v, int w, int c) {
e.push_back(Edge{v, w, c, head[u]});
head[u] = e.size() - 1;
e.push_back(Edge{u, 0, -c, head[v]});
head[v] = e.size() - 1;
}
bool SPFA() {
now.assign(head.begin(), head.end());
dis.assign(n + 1, INF);
inq.assign(n + 1, false);
queue<int> q;
dis[s] = 0, q.push(s);
while (!q.empty()) {
int u = q.front();
q.pop();
inq[u] = false;
for (int i = head[u]; ~i; i = e[i].nxt) {
int v = e[i].to;
if (e[i].w > 0 && dis[v] > dis[u] + e[i].c) {
dis[v] = dis[u] + e[i].c;
if (!inq[v])
q.push(v), inq[v] = true;
}
}
}
return dis[t] != INF;
}
int dfs(int u, int sum, int& cost) {
if (u == t)
return sum;
int flow = 0;
for (int i = head[u]; ~i && sum > 0; i = e[i].nxt) {
int v = e[i].to;
if (e[i].w > 0 && dis[v] == dis[u] + e[i].c) {
int tmp = dfs(v, min(sum, e[i].w), cost);
if (!tmp) dis[v] = INF;
e[i].w -= tmp, e[i ^ 1].w += tmp;
sum -= tmp, flow += tmp;
cost += tmp * e[i].c;
}
}
return flow;
}
pair<int, int> Dinic() {
int maxflow = 0, mincost = 0;
while (SPFA())
maxflow += dfs(s, INF, mincost);
return make_pair(maxflow, mincost);
}
private:
const int INF = 1e9;
struct Edge {int to, w, c, nxt; };
int n, s, t;
vector<Edge> e;
vector<int> head, now, dis;
vector<bool> inq;
};
const int INF = 1e9;
const int MAX_N = 3050;
int n, a[MAX_N];
int main() {
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
int s0 = n * 2 + 1, s = n * 2 + 2, t = n * 2 + 3;
MinCostMaxFlow mcmf(n * 2 + 3, s0, t);
mcmf.add_edge(s0, s, 4, 0);
for (int i = 1; i <= n; i++) {
mcmf.add_edge(s, i, INF, 0);
mcmf.add_edge(i, i + n, 1, -1);
mcmf.add_edge(i + n, t, INF, 0);
for (int j = i + 1; j <= n; j++)
if (a[i] % 7 == a[j] % 7) {
mcmf.add_edge(i + n, j, INF, 0);
mcmf.add_edge(i, j, INF, 0);
break;
}
for (int j = i + 1; j <= n; j++)
if (a[i] + 1 == a[j]) {
mcmf.add_edge(i + n, j, INF, 0);
break;
}
for (int j = i + 1; j <= n; j++)
if (a[i] - 1 == a[j]) {
mcmf.add_edge(i + n, j, INF, 0);
break;
}
for (int j = i + 1; j <= n; j++)
if (a[i] == a[j]) {
mcmf.add_edge(i, j, INF, 0);
break;
}
}
auto ans = mcmf.Dinic();
cout << -ans.second << '\n';
return 0;
}
为什么在第二个样例死循环了
最新发布