CF1137C Museums Tour
题目传送门
思路:
带阴间题
这题关键在于想到建分层图。
我们设第
i
i
i 层的
n
n
n 个点表示星期
i
i
i 的
n
n
n 个博物馆的
0
/
1
0/1
0/1 状态。
建图的时候对于一条边
(
u
,
v
)
(u,v)
(u,v),我们从第
i
i
i 天的
u
u
u 连向第
i
+
1
i+1
i+1 天的
v
v
v。
然后对于这个图进行缩点(这还挺显然的 ),再对于这个
D
A
G
DAG
DAG 跑一个最长链就好啦!
但有一些细节,怎么判断同一个
u
u
u 在
i
,
j
i,j
i,j 两天有没有重复计算呢?
对于
u
i
u_i
ui 和
u
j
u_j
uj 在同一个强连通分量的情况,我们只需要记录一下已经产生贡献的点就不会重复了
但是对于
u
i
u_i
ui 和
u
j
u_j
uj 不在同一强连通分量的情况就有点麻烦。
如果
u
i
u_i
ui 能到达
u
j
u_j
uj,那么说明
u
u
u 这个点经过
j
−
i
j-i
j−i 天能走回自己,所以走
d
−
1
d-1
d−1 次就能就能走回
u
i
u_i
ui 这个点,说明
u
j
u_j
uj 能到达
u
i
u_i
ui,即
u
i
u_i
ui 和
u
j
u_j
uj 能相互到达,这与
u
i
u_i
ui 和
u
j
u_j
uj 不在同一强连通分量相悖,所以这种情况不存在。
然后我们就切掉了这道紫题QwQ
代码:
#include<bits/stdc++.h>
#define freo(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
#define ll long long
#define id(i,j) ((i-1)*d+j)
using namespace std;
const int maxn=1e7+5;
int n,m,d,head[maxn],ecnt,low[maxn],st[maxn],top,dfn[maxn];
int cnt,tot,col[maxn],buc[maxn],vis[maxn];
struct edge
{
int nxt,to;
}e[maxn];
inline ll read()
{
ll ret=0;char ch=' ',c=getchar();
while(!(c<='9'&&c>='0')) ch=c,c=getchar();
while(c<='9'&&c>='0') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
return ch=='-'?-ret:ret;
}
inline void add(int x,int y)
{
e[++ecnt]=(edge){head[x],y};
head[x]=ecnt;
}
inline void tarjan(int u)
{
dfn[u]=low[u]=++cnt;st[++top]=u;
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
else if(!col[v]) low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
col[u]=++tot;
if(vis[u]&&buc[(u+d-1)/d]!=tot) buc[(u+d-1)/d]=tot,low[tot]++;
while(st[top]!=u)
{
int now=st[top--];
col[now]=tot;
if(vis[now]&&buc[(now+d-1)/d]!=tot) buc[(now+d-1)/d]=tot,low[tot]++;
}
top--;
}
}
inline int dfs(int u)
{
if(~dfn[u]) return dfn[u];
dfn[u]=low[u];
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
dfn[u]=max(dfn[u],low[u]+dfs(v));
}
return dfn[u];
}
int main()
{
n=read(),m=read(),d=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
for(int j=1;j<=d;j++) add(id(u,j),id(v,j%d+1));
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=d;j++)
{
int x=id(i,j);
scanf("%1d",&vis[x]);
}
}
tot=id(n,d);
for(int i=1;i<=id(n,d);i++) if(!dfn[i]) tarjan(i);
for(int u=1;u<=id(n,d);u++)
{
for(int i=head[u];i;i=e[i].nxt)
{
int v=e[i].to;
if(col[u]!=col[v]) add(col[u],col[v]);
}
}
memset(dfn,-1,sizeof(dfn));
printf("%d\n",dfs(col[id(1,1)]));
}