P4645 [COCI2006-2007#3] BICIKLI - 洛谷 | 计算机科学教育新生态
思路:
我们考虑输出inf的情况,可以发现当从1出发到2经过的任意一个点处于一个环内时,路径条数是无穷多的。
有向图上从s到t的经过点,就是从s出发所能经过的所有点与从t出发在反图上所能经过的所有点的交集。
进行拓扑排序时的点的入度,是从s出发所能经过的所有点与从t出发在反图上所能经过的所有点的交集的这张图上的入读,那些不能既被s经过又被t经过的点到这张图上的边所提供的入度是无用的。
Code:
cpp
constexpr int N=1e5+5,mod=1e9;
#define fi first
#define se second
int n,m;
int low[N],dfn[N],stk[N],instk[N],tot,top;
int scc[N],sz[N],cnt;
vector<int> e[N],e1[N];
PII p[N];
bool vis1[N],vis2[N];
int d[N],ans[N];
void Tarjan(int u)
{
dfn[u]=low[u]=++tot;
stk[++top]=u,instk[u]=1;
for(auto t:e[u])
{
if(!dfn[t])
{
Tarjan(t);
low[u]=min(low[u],low[t]);
}
else if(instk[t]) low[u]=min(low[u],dfn[t]);
}
if(dfn[u]==low[u])
{
int y;
++cnt;
do{
y=stk[top--];instk[y]=0;
scc[y]=cnt;
sz[cnt]++;
}while(y!=u);
}
}
void dfs1(int u)
{
if(vis1[u]) return ;
vis1[u]=true;
for(auto t:e[u])
{
dfs1(t);
d[t]++;
}
}
void dfs2(int u)
{
if(vis2[u]) return ;
vis2[u]=true;
for(auto t:e1[u])
{
dfs2(t);
}
}
void solve()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>p[i].fi>>p[i].se;
e[p[i].fi].push_back(p[i].se);
e1[p[i].se].push_back(p[i].fi);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) Tarjan(i);
dfs1(1),dfs2(2);
for(int i=1;i<=n;i++)
{
if(vis1[i]&&vis2[i]&&sz[scc[i]]!=1)
{
cout<<"inf";
return ;
}
}
queue<int> q;
q.push(1);
ans[1]=1;
while(q.size())
{
int t=q.front();q.pop();
for(int v:e[t])
{
if(vis2[v])
{
ans[v]=(ans[v]+ans[t])%mod;
d[v]--;
if(!d[v]) q.push(v);
}
}
}
cout<<ans[2];
}