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\n",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\n",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\n",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\n",i,sccno[i]);
    // for(int i=1;i<=scccnt;i++)
    //     printf("sccnum[%d]=%d\n",i,sccnum[i]);
    printf("%d\n",dfs(sccno[1]));
    return 0;
}
posted @ 2019-03-27 00:50  dreagonm  阅读(161)  评论(0编辑  收藏  举报