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;
}