• 洛咕 P2403 [SDOI2010]所驼门王的宝藏


    简单tarjan。

    一行的横天门如果暴力连边会被卡成平方,所以只要相邻两个横天门连双向边,再随便选一个横天门向整行连边即可。纵寰门同理。ziyou门直接map暴力连边。

    然后tarjan直接dp。

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define il inline
    #define vd void
    typedef long long ll;
    il int gi(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')f=-1;
            ch=getchar();
        }
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    std::map<std::pair<int,int>,int>M;
    struct yyb{int x,y,o,i;}s[100010];
    int fir[100010],dis[1000010],nxt[1000010],id;
    il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
    il bool cmp1(const yyb&a,const yyb&b){
        if(a.x!=b.x)return a.x<b.x;
        else return a.o==1;
    }
    il bool cmp2(const yyb&a,const yyb&b){
        if(a.y!=b.y)return a.y<b.y;
        else return a.o==2;
    }
    const int dX[]={1,1,1,0,0,-1,-1,-1},dY[]={1,0,-1,1,-1,1,0,-1};
    int dfn[100010],low[100010],stk[100010],top,ins[100010],scc[100010],w[100010];
    std::vector<int>S[100010];
    il vd tarjan(int x){
        dfn[x]=low[x]=++dfn[0];stk[++top]=x;ins[x]=1;
        for(int i=fir[x];i;i=nxt[i])
            if(!dfn[dis[i]])tarjan(dis[i]),low[x]=std::min(low[x],low[dis[i]]);
            else if(ins[dis[i]])low[x]=std::min(low[x],dfn[dis[i]]);
        if(dfn[x]==low[x]){
            ++scc[0];
            while(stk[top+1]!=x)ins[stk[top]]=0,scc[stk[top]]=scc[0],S[scc[0]].push_back(stk[top]),--top;
        }
    }
    int f[100010];
    il int dp(int x){
        if(f[x])return f[x];
        for(int i=0;i<S[x].size();++i)
            for(int j=fir[S[x][i]];j;j=nxt[j])
                if(scc[dis[j]]!=x)
                    f[x]=std::max(f[x],dp(scc[dis[j]]));
        return f[x]=f[x]+S[x].size();
    }
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("2403.in","r",stdin);
        freopen("2403.out","w",stdout);
    #endif
        int n=gi(),r=gi(),c=gi();
        for(int i=1;i<=n;++i)s[i].x=gi(),s[i].y=gi(),s[i].o=gi(),s[i].i=i,M[std::make_pair(s[i].x,s[i].y)]=i;
        int lst;
        std::sort(s+1,s+n+1,cmp1);
        lst=0;
        for(int i=1;i<=n;++i){
            if(s[i].o==1){
                if(s[lst].x==s[i].x)link(s[lst].i,s[i].i),link(s[i].i,s[lst].i);
                lst=i;
            }else if(s[lst].x==s[i].x)link(s[lst].i,s[i].i);
        }
        std::sort(s+1,s+n+1,cmp2);
        lst=0;
        for(int i=1;i<=n;++i){
            if(s[i].o==2){
                if(s[lst].y==s[i].y)link(s[lst].i,s[i].i),link(s[i].i,s[lst].i);
                lst=i;
            }else if(s[lst].y==s[i].y)link(s[lst].i,s[i].i);
        }
        for(int i=1;i<=n;++i)
            if(s[i].o==3)
                for(int j=0;j<8;++j){
                    std::pair<int,int>a=std::make_pair(s[i].x+dX[j],s[i].y+dY[j]);
                    if(M.find(a)!=M.end())link(s[i].i,M[a]);
                }
        for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
        int ans=0;
        for(int i=1;i<=scc[0];++i)ans=std::max(ans,dp(i));
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    N皇后求解。万万没想到,只用一个一维数组就搞定了。还体现了回溯。
    图的存储与实现(一),使用邻接矩阵
    201671010139 2016-2017-2 《Java程序设计》关于java的初学体验总结
    题目常用解法
    【问题】如何批量导出AI文件里内嵌的图片
    安全算法基础(一)
    对安全的认知
    6月
    渗透--还是tp
    c++学习————VC报错解决方案(vc2013)
  • 原文地址:https://www.cnblogs.com/xzz_233/p/9815904.html
Copyright © 2020-2023  润新知