zoukankan      html  css  js  c++  java
  • 题解 P2403 【[DOI2010]所驼门王的宝藏】

    题目链接:Link

    Problem

    Solution

    这道题目本质上和P3387【模板】缩点很像,但这道题主要的麻烦之处在于建图。如果暴力建图的话,时间复杂度是(O(n^2))的,肯定会挂,所以我们可以把1类和2类分开处理,每一类按对应的行或列串成若干环,环上选一点引向同行或列的其它点,至于3类,直接暴力处理即可。
    坑点:

    • 为了方便dp前的拓扑排序,SCC的边需要去重
    • 千万要区分“边id”和“点id”,别敲错变量名

    Code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<map>
    #include<cassert>
    using namespace std;
    #define mkp make_pair
    const int maxn=1e5+5;
    const int maxrc=1e6+5;
    int n,r,c,x[maxn],y[maxn],T[maxn],dfn[maxn],lowlink[maxn],sccno[maxn],dfs_cnt,scc_cnt,f[maxn],p[maxn],p_cnt,in[maxn],tt[maxn];
    vector<int> CR[maxrc],CC[maxrc],SR[maxrc],SC[maxrc],A[maxn],B[maxn];
    map<pair<int,int>,int> hsh;
    stack<int> S;
    void dfs(int u)
    {
        dfn[u]=lowlink[u]=++dfs_cnt;
        S.push(u);
        for(int v:A[u])
            if(!dfn[v])
            {
                dfs(v);
                lowlink[u]=min(lowlink[u],lowlink[v]);
            }
            else if(!sccno[v]) lowlink[u]=min(lowlink[u],dfn[v]);
        if(lowlink[u]==dfn[u])
        {
            scc_cnt++;
            while(true)
            {
                int x=S.top(); S.pop();
                sccno[x]=scc_cnt;
                if(x==u) break;
            }
        }
    }
    int main()
    {
    #ifdef local
        freopen("pro.in","r",stdin);
    #endif
        scanf("%d%d%d",&n,&r,&c);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&x[i],&y[i],&T[i]);
            hsh[mkp(x[i],y[i])]=i;
            if(T[i]==1)
            {
                CR[x[i]].push_back(i);
                SC[y[i]].push_back(i);
            }
            if(T[i]==2)
            {
                CC[y[i]].push_back(i);
                SR[x[i]].push_back(i);
            }
            if(T[i]==3)
            {
                SR[x[i]].push_back(i);
                SC[y[i]].push_back(i);
            }
        }
        for(int i=1;i<=r;i++)
        {
            int tot=CR[i].size();
            if(tot==0) continue;
            int u=CR[i][0];
            for(int v:SR[i]) A[u].push_back(v);
            if(tot==1) continue;
            for(int j=0;j<tot;j++) A[CR[i][j]].push_back(CR[i][(j+1)%tot]);
        }
        for(int i=1;i<=c;i++)
        {
            int tot=CC[i].size();
            if(tot==0) continue;
            int u=CC[i][0];
            for(int v:SC[i]) A[u].push_back(v);
            if(tot==1) continue;
            for(int j=0;j<tot;j++) A[CC[i][j]].push_back(CC[i][(j+1)%tot]);
        }
        int dr[]={-1,-1,-1,0,1,1,1,0},dc[]={-1,0,1,1,1,0,-1,-1};
        for(int i=1;i<=n;i++) for(int j=0;j<8;j++) if(T[i]==3)
        {
            int nr=x[i]+dr[j],nc=y[i]+dc[j];
            if(hsh.find(mkp(nr,nc))!=hsh.end()) A[i].push_back(hsh[mkp(nr,nc)]);
        }
        //printf("Edges:
    ");
        for(int i=1;i<=n;i++)
        {
            sort(A[i].begin(),A[i].end());
            int len=unique(A[i].begin(),A[i].end())-A[i].begin();
            A[i].resize(len);
        //	for(int v:A[i]) printf("%d -> %d
    ",i,v);
        }
        //printf("
    ");
        for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
        for(int i=1;i<=n;i++) f[sccno[i]]++;
        for(int u=1;u<=n;u++) for(int v:A[u]) if(sccno[v]!=sccno[u]) B[sccno[u]].push_back(sccno[v]);
        for(int i=1;i<=scc_cnt;i++)
        {
            sort(B[i].begin(),B[i].end());
            int len=unique(B[i].begin(),B[i].end())-B[i].begin();
            B[i].resize(len);
            for(int v:B[i]) in[v]++;
            tt[i]=f[i];
        }
        stack<int> stk;
        for(int i=1;i<=scc_cnt;i++) if(!in[i]) stk.push(i);
        while(stk.size())
        {
            int u=stk.top(); stk.pop(); p[++p_cnt]=u;
            for(int v:B[u])
            {
                in[v]--;
                if(!in[v]) stk.push(v);
            }
        }
        int res=0;
        for(int i=1;i<=scc_cnt;i++)
        {
            int u=p[i];
            for(int v:B[u]) f[v]=max(f[v],f[u]+tt[v]);
            res=max(res,f[u]);
        }
        printf("%d
    ",res);
        return 0;
    }
    
  • 相关阅读:
    el-select remote 远程搜索 多个共享一个options,options改变时输入框值不显示名称的问题
    vue 中数据共享的方式
    关于AI本质的思考
    人工智能——一场精妙的商业炒作
    相关下载链接
    只用两个问题通关《极限挑战皇家宝藏》最后一关
    常见图片格式详解
    改写《python基础教程》中的一个例子
    介绍四款windows下的神器
    实现windows批处理下的计时功能
  • 原文地址:https://www.cnblogs.com/happyZYM/p/11379551.html
Copyright © 2011-2022 走看看