P4645 [COCI2006-2007#3] BICIKLI 题解
Fishing_Boat · · 题解
题解区基本全是正着搜一遍再反着搜一遍,来一篇缩点的题解。
无限走的情况很容易让人想到强联通分量,假设走到一个大小大于等于
缩点后跑一遍拓补排序即可,下面上代码。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
#define rst(a,x) memset(a,x,sizeof(a))
#define ls p<<1
#define rs p<<1|1
#define FAST ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
using namespace std;
const int N(1e5+5);
const int P(1e9);
int n,m,dfn[N],low[N],tot,cnt,scc[N],sta[N],tp,sz[N],dp[N],st,ed,in[N],wrong[N];
vector <int> G[N],g[N];
void tarjan(int u){
dfn[u]=low[u]=++tot;sta[++tp]=u;
for(auto v:G[u]){
if(!dfn[v]){
tarjan(v);
cmin(low[u],low[v]);
}else if(!scc[v]){
cmin(low[u],low[v]);
}
}
if(dfn[u]==low[u]){
int v;cnt++;
do{
v=sta[tp--];
scc[v]=cnt;
sz[cnt]++;
if(v==2) ed=cnt;
if(v==1) st=cnt;
}while(u!=v);
}
}
struct edge{
int u,v;
}e[N];
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
G[u].push_back(v);
e[i]={u,v};
}
tarjan(1);
for(int i=1;i<=m;i++){
if(scc[e[i].u]!=scc[e[i].v]&&scc[e[i].u]&&scc[e[i].v]){
g[scc[e[i].u]].push_back(scc[e[i].v]);
in[scc[e[i].v]]++;
}
}
queue <int> q;
for(int i=1;i<=cnt;i++){
if(!in[i]){
q.push(i);
}
if(sz[i]>1) wrong[i]=1;
if(ed==i&&sz[i]==2) wrong[i]=0;
}
dp[st]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(auto v:g[u]){
wrong[v]|=wrong[u];
dp[v]+=dp[u];dp[v]%=P;
in[v]--;
if(!in[v]) q.push(v);
}
}
if(wrong[ed]) cout<<"inf";
else cout<<dp[ed];
return 0;
}