題目鏈接:點我啊╭(╯^╰)╮
題目大意:
的圖,有 個寶藏點,寶藏點有有傳送門
傳送門分三種:橫向任意飛、縱向任意飛、九宮格內任意飛
初始點任意,求最多得到幾個寶藏???
解題思路:
一眼望去縮點後 。。。(也許真的是一眼吧)
關鍵難點在於建圖,如果有 個橫向的門,那麼邊數就成 了
發現一個連通分量的點直接縮掉,也就是在同一行的橫向門當成環處理即可
對於在同一行的非橫向門,建一條環指向這個點的邊即可
所以排序處理一下即可,細節頗多,縱向門也同樣處理
九宮格門直接暴力建即可
跑完 之後求個最長路即可
#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
const int maxn = 1e5 + 5;
int dx[10] = {1, 1, 1, 0, 0, -1, -1, -1};
int dy[10] = {1, 0, -1, 1, -1, 1, 0, -1};
map <pii, int> mp;
vector <int> g[maxn], g2[maxn];
struct node{
int x, y, op, id;
} p[maxn];
int n, r, c, ans, tot, top, numc;
int dfn[maxn], low[maxn], vis[maxn], st[maxn];
int dp[maxn], sum[maxn], col[maxn];
inline void add(int u, int v){
g[u].push_back(v);
}
bool xcmp(const node &A, const node &B){
if(A.x ^ B.x) return A.x < B.x;
if(A.op == 1) return true;
if(B.op == 1) return false;
return A.y < B.y;
}
bool ycmp(const node &A, const node &B){
if(A.y ^ B.y) return A.y < B.y;
if(A.op == 2) return true;
if(B.op == 2) return false;
return A.x < B.x;
}
void tarjan(int u){
dfn[u] = low[u] = ++tot;
st[++top] = u;
vis[u] = 1;
for(auto v : g[u]){
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
} else if(vis[v]) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]){
++numc;
while(st[top+1] ^ u){
col[st[top]] = numc;
sum[numc]++;
vis[st[top--]] = 0;
}
}
}
void dfs(int u, int fa){
if(dp[u] > sum[u]) return;
dp[u] = sum[u];
for(auto v : g2[u]){
if(v == fa) continue;
dfs(v, u);
dp[u] = max(dp[u], dp[v] + sum[u]);
}
}
signed main() {
scanf("%d%d%d", &n, &r, &c);
for(int i=1; i<=n; i++){
scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].op);
p[i].id = mp[{p[i].x, p[i].y}] = i;
}
sort(p+1, p+1+n, xcmp);
for(int i=1, fi=1, la=1; i<=n; i++){
if(p[i].x ^ p[i+1].x){
if(fi ^ la) add(p[la].id, p[fi].id);
fi = la = i + 1;
} else{
if(p[la].op == 1) add(p[la].id, p[i+1].id);
if(p[i+1].op == 1) la = i + 1;
if(p[fi].op ^ 1) fi = la = i + 1;
}
}
sort(p+1, p+1+n, ycmp);
for(int i=1, fi=1, la=1; i<=n; i++){
if(p[i].y ^ p[i+1].y){
if(fi ^ la) add(p[la].id, p[fi].id);
fi = la = i + 1;
} else{
if(p[la].op == 2) add(p[la].id, p[i+1].id);
if(p[i+1].op == 2) la = i + 1;
if(p[fi].op ^ 2) fi = la = i + 1;
}
}
for(int i=1; i<=n; i++){
if(p[i].op ^ 3) continue;
for(int j=0; j<8; j++)
if(mp.count({p[i].x+dx[j], p[i].y+dy[j]}))
add(p[i].id, mp[{p[i].x+dx[j], p[i].y+dy[j]}]);
}
for(int i=1; i<=n; i++)
if(!dfn[i]) tarjan(i);
for(int i=1; i<=n; i++) {
for(auto v : g[i])
if(col[i] ^ col[v])
g2[col[i]].push_back(col[v]);
}
for(int i=1; i<=numc; i++){
if(dp[i] <= sum[i]) dfs(i, 0);
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
}