• CF1137C Museums Tour


    思路

    强连通分量的好题
    对于每个博物馆,因为时间的限制条件,不好直接统计,
    发现d很小,可以建出d层分层图,原图<u,v>的边变成<u,i>到<v,i+1>的边,<u,n>变成<v,1>的边,然后跑SCC,拆出每个点权值就是这个点这个时间有无贡献,此时一个强连通分量全选就能获得最大的价值了,然后注意同一个i只会出现在一个SCC中且只能被统计一次,所以要去下重

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    #include <set>
    #include <bitset>
    using namespace std;
    int cnt,v[5000100],fir[5000100],nxt[5000100],dfn[5000100],dfs_clock,low[5000100],sccno[5000100],vis[5000100],scccnt,sccnum[5000100],d,n,m;
    set<int> scc_S[5000100];
    stack<int> S;
    bitset<100100> mat[51];
    inline void addedge(int ui,int vi){
        // printf("add:%d -> %d
    ",ui,vi);
        ++cnt;
        v[cnt]=vi;
        nxt[cnt]=fir[ui];
        fir[ui]=cnt;
    }
    int cnt2,v2[5000100],fir2[5000100],nxt2[5000100];
    inline void addedge2(int ui,int vi){
        // printf("add2:%d -> %d
    ",ui,vi);
        ++cnt2;
        v2[cnt2]=vi;
        nxt2[cnt2]=fir2[ui];
        fir2[ui]=cnt2;
    }
    inline void tarjan(int u){
        dfn[u]=low[u]=++dfs_clock;
        vis[u]=true;
        S.push(u);
        for(int i=fir[u];i;i=nxt[i]){
            if(!dfn[v[i]]){
                tarjan(v[i]);
                low[u]=min(low[u],low[v[i]]);
            }
            else if(vis[v[i]]){
                low[u]=min(low[u],low[v[i]]);
            }
        }
        if(low[u]==dfn[u]){
            ++scccnt;
            while(1){
                int x=S.top();
                S.pop();
                vis[x]=false;
                sccno[x]=scccnt;
                if(x==u)
                    break;
            }
        }
    }
    inline void sd(void){
        for(int i=1;i<=d*n;i++)
            if(!dfn[i])
                tarjan(i);
        for(int i=1;i<=d;i++)
            for(int j=1;j<=n;j++){
                if(mat[i][j])
                    scc_S[sccno[j+(i-1)*n]].insert(j);
                for(int k=fir[j+(i-1)*n];k;k=nxt[k])
                    if(sccno[j+(i-1)*n]!=sccno[v[k]])
                        addedge2(sccno[j+(i-1)*n],sccno[v[k]]);
            }
        for(int i=1;i<=scccnt;i++)
            sccnum[i]=scc_S[i].size();
    }
    int dp[5000100];
    bitset<5000100> visx;
    inline int dfs(int o){
        // printf("u=%d
    ",o);
        if(visx[o])
            return dp[o];
        visx[o]=true;
        for(int i=fir2[o];i;i=nxt2[i]){
            dp[o]=max(dfs(v2[i]),dp[o]);
        }
        dp[o]+=sccnum[o];
        return dp[o];
    }
    int main(){
        scanf("%d %d %d",&n,&m,&d);
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d %d",&a,&b);
            for(int j=1;j<d;j++)
                addedge(a+(j-1)*n,b+j*n);
            addedge(a+(d-1)*n,b);
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=d;j++){
                char c=getchar();
                while(c!='0'&&c!='1'){
                    c=getchar();
                }
                mat[j][i]=c-'0';
            }
        sd();
        // for(int i=1;i<=n*d;i++)
        //     printf("sccno[%d]=%d
    ",i,sccno[i]);
        // for(int i=1;i<=scccnt;i++)
        //     printf("sccnum[%d]=%d
    ",i,sccnum[i]);
        printf("%d
    ",dfs(sccno[1]));
        return 0;
    }
    
  • 相关阅读:
    Android中开发习惯
    Activity、Window和View三者间的关系有一定的见解
    Android底层有一定的认识,研究过相关的Android源码
    安卓工程的启动过程
    OAuth2认证有一定的了解
    屏幕适配经验
    NOIP模拟赛14
    NOIP模拟赛13
    NOIP模拟赛12
    NOIP模拟赛11
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10604944.html
Copyright © 2020-2023  润新知