BZOJ 1924 Sdoi2010 所驼门王的宝藏

题目

题解:
对于同方向(横竖的),同行最近相邻的两个连边。每个关键点被左右最近横向点连边,被上下最近纵向点连边,*门按题意连,没有宝藏的点不连边,求强连通分量缩点后跑拓扑排序即可。
我打的好长啊。

AC Code:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define maxn 1000006
#define maxm 100005
#define pb push_back
#define pii pair<int,int>
#define mp make_pair
#define F first
#define S second
using namespace std;
 
int n,r,c,cnt,in[maxm];
vector<int>h[maxn],z[maxn];
vector<pii>zy;
 
map<pii,int>st;
vector<int>G[maxm],V[maxm];
 
int sta[maxm],dfn[maxm],low[maxm],bl[maxm],siz[maxm],dis[maxm],scc,tim;
void dfs(int u){
    dfn[u] = low[u] = ++tim;
    sta[++sta[0]] = u;
    for(int i=0,v;i<G[u].size();i++)
        if(!dfn[v=G[u][i]]){
            dfs(v);
            low[u] = min(low[u] , low[v]);
        }
        else if(!bl[v]){
            low[u] = min(low[u] , dfn[v]);
        }
    if(low[u] == dfn[u]){
        scc++;
        for(int t=-1;t!=u;){
            bl[t = sta[sta[0]--]] = scc;
            siz[scc]++;
        }
    }
}
 
int main(){
    scanf("%d%d%d",&n,&r,&c);   
    for(int i=1;i<=n;i++){
        int x,y,t;
        scanf("%d%d%d",&x,&y,&t);
        if(t == 1) h[x].pb(y);
        if(t == 2) z[y].pb(x);
        if(t == 3) zy.pb(mp(x,y));
        st[mp(x,y)] = ++cnt;
    }
    for(int i=1;i<=r;i++)
        if(!h[i].empty()){
            sort(h[i].begin(),h[i].end());
            for(int j=0,pr=0;j<h[i].size();j++){
                int p = h[i][j];
                if(j){
                    int npr = st[mp(i,p)];
                    G[npr].pb(pr),G[pr].pb(npr);
                    pr = npr;
                }
                else pr = st[mp(i,p)];
            }
        }
    for(int i=1;i<=c;i++)
        if(!z[i].empty()){
            sort(z[i].begin(),z[i].end());
            for(int j=0,pr=0;j<z[i].size();j++){
                int p = z[i][j];
                if(j){
                    int npr = st[mp(p,i)];
                    G[npr].pb(pr) , G[pr].pb(npr);
                    pr = npr; 
                }
                else pr = st[mp(p,i)];
            }
        }
    for(int i=0;i<zy.size();i++){
        int p = st[zy[i]];
        vector<int>::iterator t = lower_bound(h[zy[i].F].begin(),h[zy[i].F].end(),zy[i].S);
        if(t != h[zy[i].F].end())
            G[st[mp(zy[i].F,*t)]].pb(p);
        if(t != h[zy[i].F].begin()){
            t--;
            G[st[mp(zy[i].F,*t)]].pb(p);
        }
         
        t = lower_bound(z[zy[i].S].begin(),z[zy[i].S].end(),zy[i].F);
        if(t != z[zy[i].S].end())
            G[st[mp(*t,zy[i].S)]].pb(p);
        if(t != z[zy[i].S].begin()){
            t--;
            G[st[mp(*t,zy[i].S)]].pb(p);
        }
         
         
        for(int j=max(-1,1-zy[i].F);j<=min(1,r-zy[i].F);j++)
            for(int k=max(-1,1-zy[i].S);k<=min(1,c-zy[i].S);k++)
                if(j || k){
                    int u = zy[i].F + j , v = zy[i].S + k;
                    if(!st.count(mp(u,v))) continue;
                    G[p].pb(st[mp(u,v)]);
                }
    }
     
    for(int i=1;i<=r;i++)
        if(!h[i].empty()){
            for(int j=0;j<h[i].size();j++){
                int pp = h[i][j] , p = st[mp(i,pp)];
                vector<int>::iterator t = lower_bound(z[pp].begin(),z[pp].end(),i);
                if(t != z[pp].end())
                    G[st[mp(*t,pp)]].pb(p);
                if(t != z[pp].begin())      
                    t--,
                    G[st[mp(*t,pp)]].pb(p);
            }
        }
         
    for(int i=1;i<=c;i++)
        if(!z[i].empty()){
            for(int j=0;j<z[i].size();j++){
                int pp = z[i][j] , p = st[mp(pp,i)];
                vector<int>::iterator t = lower_bound(h[pp].begin(),h[pp].end(),i);
                if(t != h[pp].end())
                    G[st[mp(pp,*t)]].pb(p);
                if(t != h[pp].begin())
                    t--,
                    G[st[mp(pp,*t)]].pb(p);
            }
        }
     
    for(int i=1;i<=cnt;i++)
        if(!dfn[i])
            dfs(i);
             
    for(int i=1;i<=cnt;i++)
        for(int j=0,v;j<G[i].size();j++)
            if(bl[i] != bl[v=G[i][j]])
                V[bl[i]].pb(bl[v]) , in[bl[v]] ++;
     
    queue<int>q;
    for(int i=1;i<=scc;i++)
        if(!in[i])  
            q.push(i) , dis[i] = siz[i];
    int ans = 0;
    for(int u;!q.empty();){
        u = q.front() , q.pop();
        ans = max(ans , dis[u]);
        for(int j=0,v;j<V[u].size();j++){
            in[v=V[u][j]] --;
            dis[v] = max(dis[v] , dis[u] + siz[v]);
            if(!in[v]) q.push(v);
        }
    }
     
    printf("%d\n",ans);
}
上一篇:一文看懂 HashMap 中的红黑树实现原理


下一篇:1003 我要通过!(PAT)