1 条题解
-
0
自动搬运
来自洛谷,原作者为

06ray
再见了,OI搬运于
2025-08-24 22:02:14,当前版本为作者最后更新于2018-08-02 17:59:17,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
先膜楼下的chen_zhe大佬%%%
这题思路不难,可能是道假紫题。
大体思路如下:
先判断从1到2点是否有无限条路径。什么时候就会有无限条路径呢?不难想到,当出现一个环且从1节点到2节点能经过它时,就会有无数条路径可走。判断是否有环的方法很简单,只需要求强连通分量(tarjan模板不阐述)。
求好之后我们还得判断从1节点到2节点是否可以遍历到一个环,可以用一个BFS来模拟。我们先用BFS求出从1号节点出发能遍历到的所有的点。然后我们建一个反向的图,再用BFS求出在反向图中从2号点出发能遍历到的所有的点。接着判断如果某一个点既可以被2遍历到又能被1遍历到并且它在一个环之内,就说明有无限条路径,输出inf。
最后,我们在用一个BFS求出从1号点到2号点的路径总数即可。
下面有请
可爱丑陋的代码酱出场qwq#include<bits/stdc++.h> using namespace std; const int MAXN=101000; struct edge{ int to,cost; }; stack<int> s; int n,m,dfn[MAXN],low[MAXN],color[MAXN],vis[MAXN],used[MAXN],a[MAXN],countt[MAXN],in[MAXN]; int colornum; vector<int> G[MAXN]; vector<int> rG[MAXN]; inline int read()//读入优化 { int num=0; char ch=getchar(); while(ch>'9'||ch<'0') ch=getchar(); while(ch>='0'&&ch<='9') { num=num*10+ch-'0'; ch=getchar(); } return num; } int cnt; void tarjan(int u)//Tarjan模板,求出强连通分量 { cnt++; dfn[u]=low[u]=cnt; used[u]=true; s.push(u); vis[u]=true; for(int i=0; i<G[u].size(); i++) { int v=G[u][i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else { if(vis[v]) { low[u]=min(low[u],dfn[v]); } } } if(dfn[u]==low[u]) { colornum++; while(s.top()!=u) { int t=s.top(); s.pop(); color[t]=colornum; vis[t]=false; } s.pop(); color[u]=colornum; vis[u]=false; } } void bfs1(int x)//求出从1号节点出发能遍历到的所有的点 { memset(used,0,sizeof(used)); queue<int>q; q.push(x); used[x]=true; while(!q.empty()) { int v=q.front(); q.pop(); for(int i=0; i<G[v].size(); i++) { if(!used[G[v][i]]) { used[G[v][i]]=true;//判断是否能被1遍历到 q.push(G[v][i]); } in[G[v][i]]++; } } } void bfs2(int x)//求出在逆向图中从2号节点出发能遍历到的所有的点 { memset(vis,0,sizeof(vis)); queue<int>q; q.push(x); vis[x]=true; while(!q.empty()) { int v=q.front(); q.pop(); for(int i=0; i<rG[v].size(); i++) { if(!vis[rG[v][i]]) { vis[rG[v][i]]=true;//判断是否能被2遍历到 q.push(rG[v][i]); } } } } void bfs3(int x) { queue<int>q; q.push(x); countt[x]=1; while(!q.empty()) { int v=q.front(); q.pop(); for(int i=0; i<G[v].size(); i++) { if(vis[G[v][i]]) { countt[G[v][i]]+=countt[v]; countt[G[v][i]]%=1000000000;//取模 if(!--in[G[v][i]]) q.push(G[v][i]);//小优化 } } } } int main() { cin>>n>>m; for(int i=1; i<=m; i++) { int x,y; x=read(),y=read(); G[x].push_back(y);//邻接表存储 rG[y].push_back(x);//建反向图 } for(int i=1; i<=n; i++) if(!dfn[i]) tarjan(i); bfs1(1); bfs2(2); for(int i=1; i<=n; i++) a[color[i]]++;//统计每个强连通分中节点个数 for(int i=1; i<=n; i++) if(used[i]&&vis[i]&&a[color[i]]!=1)//可以被2遍历到又能被1遍历到并且在一个环之内 { cout<<"inf"; return 0; } bfs3(1); cout<<countt[2]; return 0; }管理大大求过
- 1
信息
- ID
- 3656
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 4
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者