Luogu 2403 [SDOI2010]所驼门王的宝藏
BZOJ 1924
内存要算准,我MLE了两次。
建立$n + r + c$个点,对于一个点$i$的坐标为$(x, y)$,连边$(n + x, i)$和$(n + r + y, i)$,代表这一列和这一行可以走到它,如果类型为$1, 2$只要连一条到所在行和所在列的边就可以了,但是类型$3$似乎没有什么好的方法,$map$或者$hash$搞一搞,暴力连一连。
然后缩点之后记忆化搜索一下就可求出最长链了。
点数为$n + r + c$最多不超过$2e6 + 1e5$,边数为$2e5 + $最多$8e5$,不会达到这个上界。
时间复杂度$O(nlogn)$,$log$来源于$map$。
Code:
#include <cstdio> #include <cstring> #include <map> #include <iostream> #include <vector> using namespace std; typedef pair <int, int> pin; const int N = 2e6 + 1e5 + 5; const int M = 1e6 + 5; const int dx[] = {-1, -1, -1, 0, 0, 1, 1, 1}; const int dy[] = {-1, 0, 1, -1, 1, -1, 0, 1}; int n, r, c, tot = 0, head[N], scc = 0, bel[N], f[N]; int dfsc = 0, dfn[N], low[N], top = 0, stk[N], deg[N]; bool vis[N]; map <pin, int> mp; vector <int> G[N]; struct Edge { int to, nxt; } e[M]; inline void add(int from, int to) { e[++tot].to = to; e[tot].nxt = head[from]; head[from] = tot; } struct Node { int x, y, type; } a[N]; inline void read(int &X) { X = 0; char ch = 0; int op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } inline void chkMax(int &x, int y) { if(y > x) x = y; } inline int min(int x, int y) { return x > y ? y : x; } void tarjan(int x) { dfn[x] = low[x] = ++dfsc; vis[x] = 1, stk[++top] = x; for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if(!dfn[y]) { tarjan(y); low[x] = min(low[x], low[y]); } else if(vis[y]) low[x] = min(low[x], dfn[y]); } if(low[x] == dfn[x]) { ++scc; for(; stk[top + 1] != x; --top) { vis[stk[top]] = 0; bel[stk[top]] = scc; if(stk[top] >= 1 && stk[top] <= n) ++f[scc]; } } } void dfs(int x) { if(vis[x]) return; int res = 0, vecSiz = G[x].size(); for(int i = 0; i < vecSiz; i++) { int y = G[x][i]; dfs(y); chkMax(res, f[y]); } f[x] += res; vis[x] = 1; } int main() { read(n), read(r), read(c); for(int i = 1; i <= n; i++) { read(a[i].x), read(a[i].y), read(a[i].type); mp[pin(a[i].x, a[i].y)] = i; add(a[i].x + n, i), add(a[i].y + n + r, i); } for(int i = 1; i <= n; i++) { if(a[i].type == 1) add(i, a[i].x + n); if(a[i].type == 2) add(i, a[i].y + n + r); if(a[i].type == 3) { for(int j = 0; j < 8; j++) { int tox = a[i].x + dx[j], toy = a[i].y + dy[j]; if(tox >= 1 && tox <= r && toy >= 1 && toy <= c) { if(mp.find(pin(tox, toy)) != mp.end()) add(i, mp[pin(tox, toy)]); } } } } for(int i = 1; i <= n + r + c; i++) if(!dfn[i]) tarjan(i); for(int x = 1; x <= n + r + c; x++) { for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if(bel[x] == bel[y]) continue; G[bel[x]].push_back(bel[y]); ++deg[bel[y]]; } } for(int i = 1; i <= scc; i++) if(!deg[i]) dfs(i); int ans = 0; for(int i = 1; i <= scc; i++) chkMax(ans, f[i]); printf("%d\n", ans); return 0; }