#6005
meaning of the title
Given a positive integer sequence x1 xn.
(1) Calculate the length s of the longest increasing subsequence.
(2) Calculates the maximum number of incremental subsequences of length s that can be extracted from a given sequence. (each number can only be taken once)
(3) If x1 and xn are allowed to be used multiple times in the extracted sequence, how many incremental subsequences with length s can be extracted from the given sequence at most.
thinking
The first question is: the dp of n^2 is finished, and the dp array is processed. dp[i] indicates the length of the longest non descending subsequence whose subscript is I and whose ending number is I.
Second question: each number can only be taken once. Consider using dinic to write. The traffic is the number. There are two restrictions in the process of drawing. One is that each number can only be taken once, and the other is that the length is s. The condition that only one time can be taken can be solved by splitting a point I into two points i,i+n, and then I and i+n are connected to an edge with a capacity of 1. Then if there i s a connection from point I to point J, i+n is used to connect, so that each point can be used only once, after all, the capacity is limited to 1. Next, the source point is connected with dp[i] as 1 point, and the point with dp[i] as s is connected with the sink point Connect, satisfy the point i,j of a [i] > = a [J] & & dp[i] = = DP [J] + 1, connect j+n with I, and finally find the maximum flow.
Third, X1 and xn can be used multiple times. In addition, the traffic from the source point to 1 is the edge of INF, the traffic from 1 and 1+n is the edge of INF, and the traffic from N and n+n is the edge of INF. if dp[n]==s, then the traffic from n+n to the INF of the sink point should be added. Finally, find the maximum flow.
#include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; const int maxn = 1e4 + 7; typedef long long ll; struct Edge { int from, to, cap, flow; Edge(int u, int v, int c, int f):from(u), to(v), cap(c), flow(f) {} }; struct Dinic { int n, m, s, t; vector<Edge> edges; vector<int> G[maxn]; int d[maxn], cur[maxn]; bool vis[maxn]; void init(int n) { for (int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void add(int from, int to,int cap) { edges.push_back(Edge(from, to, cap, 0)); edges.push_back(Edge(to, from, 0, 0)); m = edges.size(); G[from].push_back(m - 2); G[to].push_back(m - 1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> que; que.push(s); d[s] = 0; vis[s] = 1; while (!que.empty()) { int x = que.front(); que.pop(); for (int i = 0; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap > e.flow) { vis[e.to] = 1; d[e.to] = d[x] + 1; que.push(e.to); } } } return vis[t]; } int DFS(int x, int a) { if(x == t || a == 0) return a; int flow = 0, f; for (int &i = cur[x]; i < G[x].size(); i++) { Edge& e = edges[G[x][i]]; if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) { e.flow += f; edges[G[x][i] ^ 1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t) { this->s = s; this->t = t; int flow = 0; while (BFS()) { memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } }; int a[maxn], dp[maxn]; int main() { int n, m, s, t; scanf("%d", &n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), dp[i] = 1; int maxx = 1; for (int i = 2; i <= n; i++) { for (int j = 1; j < i; j++) if(a[i] >= a[j]) dp[i] = max(dp[i], dp[j] + 1); maxx = max(maxx, dp[i]); } if(n == 1) { printf("1\n1\n1\n"); return 0; } printf("%d\n", maxx); Dinic solve; s = 0, t = n * 2 + 1; for (int i = 1; i <= n; i++) { solve.add(i, i + n, 1); if(dp[i] == 1) solve.add(s, i, 1); if(dp[i] == maxx) solve.add(i + n, t, 1); } for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) { if(dp[j] + 1 == dp[i] && a[j] <= a[i]) solve.add(j + n, i, 1);//*** } } int ans = solve.Maxflow(s, t); printf("%d\n", ans); solve.add(s, 1, INF); solve.add(1, 1 + n, INF); solve.add(n, n + n, INF); if(dp[n] == maxx) solve.add(n + n, t, INF); ans += solve.Maxflow(s, t);//Attention is to add, because it is based on the original picture to add edge and then find the widening road. printf("%d\n", ans); }