【網路流24題】 5. 最長不下降子序列問題
阿新 • • 發佈:2020-09-06
這道題有億點難QAQ,雖然蒟蒻我已經做完了,不過我想完全理解本題以後再寫題解,所以先佔個坑QwQ
先貼一下程式碼:
發這麼晚當然是因為我看了一天番QwQ
/** * luogu P2766 https://www.luogu.com.cn/problem/P2766 * Dinic **/ #include <cstdio> #include <algorithm> #include <cstring> #include <queue> const int maxn = 5005; const int maxm = 550000; const int s = 0; const int t = maxn - 1; const int INF = 0x3f3f3f3f; using namespace std; struct Edge { int to, val, nxt; }e[maxm]; int numedge, head[maxn], n, num[maxn], f[maxn], depth[maxn], a[maxn], ans, res; inline void AddEdge(int from, int to, int val) { e[numedge].to = to; e[numedge].val = val; e[numedge].nxt = head[from]; head[from] = numedge; numedge++; } inline bool bfs() { memset(depth, 0, sizeof(depth)); depth[s] = 1; queue<int> q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; ~i; i = e[i].nxt) { int to = e[i].to; if (!depth[to] && e[i].val > 0) { depth[to] = depth[u] + 1; q.push(to); } } } return depth[t] != 0; } int dfs(int u, int flow) { if (u == t || flow == 0) return flow; int res = 0; for (int i = head[u]; ~i; i = e[i].nxt) { int to = e[i].to; if (depth[to] == depth[u] + 1 && e[i].val > 0) { int di = dfs(to, min(flow, e[i].val)); if (di > 0) { e[i].val -= di; e[i ^ 1].val += di; flow -= di; res += di; } } } if (!res) depth[u] = 0; return res; } void Dinic() { while (bfs()) { res += dfs(s, INF); } } int main() { memset(head, -1, sizeof(head)); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", a + i); f[i] = 1; } for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) { if (a[i] >= a[j]) { f[i] = max(f[i], f[j] + 1); } } ans = max(ans, f[i]); } printf("%d\n", ans); for (int i = 1; i <= n; i++) { AddEdge(i, i + n, 1); AddEdge(i + n, i, 0); if (f[i] == 1) { AddEdge(s, i, 1); AddEdge(i, s, 0); } if (f[i] == ans) { AddEdge(i + n, t, 1); AddEdge(t, i + n, 0); } } for (int i = 2; i <= n; i++) { for (int j = 1; j < i; j++) { if (a[j] <= a[i] && f[i] == f[j] + 1) { AddEdge(j + n, i, 1); AddEdge(i, j + n, 0); } } } Dinic(); printf("%d\n", res); AddEdge(s, 1, INF); AddEdge(1, s, 0); AddEdge(1, 1 + n, INF); AddEdge(1 + n, 1, 0); if (f[n] == ans && n > 1) { AddEdge(n, n + n, INF); AddEdge(n + n, n, 0); AddEdge(n + n, t, INF); AddEdge(t, n + n, 0); } Dinic(); printf("%d\n", res); return 0; }