所用点的编号为输入顺序,因为只有在存在联通门的宫室中存在宝藏。其余点不考虑
对于每一行,选定一个横天门,向该行横天门连双向边,其余门单向边
纵列同理
自.由门用map判周围八个点是否存在,存在即连边
Tarjan缩点后DAG上dp求最长路
bzoj 可过,luogu卡空间
#include <bits/stdc++.h> #define gc getchar() inline int read() { int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x; } const int N = 1e5 + 4, M = 1e6 + 4; const int xd[] = {0, -1, -1, -1, 0, 1, 1, 1}; const int yd[] = {-1, -1, 0, 1, 1, 1, 0, -1}; int head[N], head_2[N], cnt; struct Node { int u, v, nxt; }; Node G[M], E[M]; std:: vector <int> Vecx[M], Vecy[M]; std:: map <int, int> Map[M]; int X[N], Y[N], Opt[N]; int Q, n, m; int Low[N], Dfn[N], Stack[N], Belong[N], Size[N], Scc, Tim, topp; bool vis[N]; inline void Add_1(int u, int v) { if(u == v) return ; G[++ cnt].v = v; G[cnt].nxt = head[u]; head[u] = cnt; } inline void Add_2(int u, int v) { E[++ cnt].v = v; E[cnt].nxt = head_2[u]; head_2[u] = cnt; } inline void Build() { memset(head, -1, sizeof head); for(int i = 1; i <= n; i ++) { int x = 0, s = Vecx[i].size(); for(int j = 0; j < s; j ++) { if(Opt[Vecx[i][j]] == 1) { x = Vecx[i][j]; break; } } for(int j = 0; j < s; j ++) { Add_1(x, Vecx[i][j]); if(Opt[Vecx[i][j]] == 1) Add_1(Vecx[i][j], x); } } for(int i = 1; i <= m; i ++) { int y = 0, s = Vecy[i].size(); for(int j = 0; j < s; j ++) { if(Opt[Vecy[i][j]] == 2) { y = Vecy[i][j]; break; } } for(int j = 0; j < s; j ++) { Add_1(y, Vecy[i][j]); if(Opt[Vecy[i][j]] == 2) Add_1(Vecy[i][j], y); } } for(int i = 1; i <= Q; i ++) { if(Opt[i] == 3) { for(int j = 0; j < 8; j ++) { int t = Map[X[i] + xd[j]][Y[i] + yd[j]]; if(t) Add_1(i, t); } } } } void Tarjan(int x) { Low[x] = Dfn[x] = ++ Tim; Stack[++ topp] = x; vis[x] = 1; for(int i = head[x]; ~ i; i = G[i].nxt) { int v = G[i].v; if(!Dfn[v]) { Tarjan(v); Low[x] = std:: min(Low[x], Low[v]); } else if(vis[v]) Low[x] = std:: min(Low[x], Low[v]); } if(Dfn[x] == Low[x]) { vis[x] = 0, Belong[x] = ++ Scc; Size[Scc] = 1; while(Stack[topp] != x) { vis[Stack[topp]] = 0, Belong[Stack[topp]] = Scc; topp --; Size[Scc] ++; } topp --; } } inline void Rebuild() { cnt = 0; memset(head_2, -1, sizeof head_2); for(int u = 1; u <= Q; u ++) for(int i = head[u]; ~ i; i = G[i].nxt) if(Belong[u] != Belong[G[i].v]) Add_2(Belong[u], Belong[G[i].v]); } int Answer, tot[N]; void Dfs(int u) { vis[u] = 1; for(int i = head_2[u]; ~ i; i = E[i].nxt) { int v = E[i].v; if(!vis[v]) Dfs(v); tot[u] = std:: max(tot[u], tot[v]); } tot[u] += Size[u]; Answer = std:: max(Answer, tot[u]); } int main() { Q = read(), n = read(), m = read(); for(int i = 1; i <= Q; i ++) { X[i] = read(), Y[i] = read(), Opt[i] = read(); Vecx[X[i]].push_back(i); Vecy[Y[i]].push_back(i); Map[X[i]][Y[i]] = i; } Build(); for(int i = 1; i <= Q; i ++) if(!Dfn[i]) Tarjan(i); Rebuild(); memset(vis, 0, sizeof vis); for(int i = 1; i <= Scc; i ++) if(!vis[i]) Dfs(i); std:: cout << Answer; return 0; }