链式前向星存图,Tarjan算法求强连通分量,应该可以算一个Tarjan算法的模板题了。
另:b站有个讲数据结构和算法讲得很好的up主->不分解的AgOH
注意:我Edge数组最开始开成了Edge[maxn]导致最后一个点一直段错误。
#include <iostream>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn = 10010;
const int maxm = 6 * maxn;
struct E{
int to,next;
}Edge[maxm];
int tot,Head[maxn];
void AddEdge(int u,int v){ // 加边(在邻接表每一排的第一个插入)
Edge[tot].to = v;
Edge[tot].next = Head[u];
Head[u] = tot++;
}
int tim = 1;
stack<int> s;
int dfn[maxn]; // 每个点真实被访问的时间点
int low[maxn]; // 每个点能回溯到的最早的点
bool f[maxn];
int pre[maxn]; // 类似并查集
int cnt = 1;
void tarjan(int u){
s.push(u);
dfn[u] = low[u] = tim++;
for(int i = Head[u];~i;i = Edge[i].next){ // 访问该点的所有直接相连的点
int v = Edge[i].to;
if(dfn[v] == 0){ // 这个点还没有被访问
tarjan(v);
low[u] = min(low[u],low[v]);
}else if(f[v] == false){ // 这个点仍然在栈中
low[u] = min(low[u],low[v]);
}
}
if(dfn[u] == low[u]){
// 找到了一个点
while(s.top() != u){
pre[s.top()] = cnt;
f[s.top()] = true;
s.pop();
}
pre[u] = cnt++;
s.pop();
}
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
tot = 1;
fill(Head,Head + maxn,-1);
fill(f,f + maxn,false);
for(int i = 0;i < m;i++){
int u,v;
scanf("%d%d",&u,&v);
AddEdge(u,v);
}
for(int i = 1;i <= n;i++){
if(dfn[i] == 0) tarjan(i);
}
int k;
scanf("%d",&k);
for(int i = 0;i < k;i++){
int u,v;
scanf("%d%d",&u,&v);
if(pre[u] == pre[v]) printf("Yes\n");
else printf("No\n");
}
system("pause");
return 0;
}