搜索和图论之DFS、BFS和拓扑排序
1.DFS
时间复杂度\(O(n+m)\)
例题 846. 树的重心 - AcWing题库
题目概述
找出树的重心,重心是一个节点,删除该结点后可以使得剩余连通图中点数的最大最小
解题思路
\((1)\) 每个节点在遍历时return:\(子节点个数+1\)
\((2)\) 每个节点在遍历时可计算更新:\(max(各个子树的节点的最大值,节点总数-(子节点+1))\)
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10; //节点数量
const int M=2*N; //边的数量
int h[N],e[M],ne[M],idx,re[N],tmax,tsize;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int dfs(int u)
{
re[u]=1;
int size=1,curmax=0;
for(int i=h[u];i!=-1;i=ne[i])
{
if(re[e[i]]==0)
{
int sonsize=dfs(e[i]);
size+=sonsize;
curmax=max(curmax,sonsize);
}
}
curmax=max(curmax,tsize-size);
if(curmax<tmax) tmax=curmax;
return size;
}
int main()
{
int a,b;
idx=0;
memset(h,-1,sizeof(h));
memset(re,0,sizeof(re));
cin>>tsize;
tmax=tsize;
for(int i=1;i<tsize;i++)
{
cin>>a>>b;
add(a,b);
add(b,a);
}
dfs(1);
cout<<tmax;
return 0;
}
2.BFS
时间复杂度\(O(m+n)\)
例题 847. 图中点的层次 - AcWing题库
题目概述
所有边的长度为 \(1\),求 \(1-n\) 的最短路径
解题思路
\(d[j]\) 表示 \(1-j\) 的距离初始化为 \(\infty\)
完整代码
#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e5+10; //节点数量
const int M=2*N; //边的数量
int h[N],d[N],e[M],ne[M],idx=0,re[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void bfs(int u)
{
queue<int> q;
re[u]=1;
q.push(u);
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(!re[j])
{
re[j]=1;
d[j]=d[t]+1;
q.push(j);
}
}
}
}
int main()
{
int n,m,a,b;
cin>>n>>m;
memset(h,-1,sizeof h);
memset(d,INF,sizeof d);
d[1]=0;
for(int i=1;i<=m;i++)
{
cin>>a>>b;
add(a,b);
}
bfs(1);
if(d[n]==INF) cout<<-1;
else cout<<d[n];
return 0;
}
3.拓扑排序
定义:拓扑序列中所有节点都是从前指向后(针对有向图)
有向无环图一定存在拓扑序列,因而有向无环图也被成为拓扑图
例题 848. 有向图的拓扑序列 - AcWing题库
题目概述
求一有向图的拓扑序列
解题思路
\((1)\) 利用 \(d[j]\) 记录 \(j\) 节点的入度
\((2)\) 数组模拟队列:\(hh=0,tt=0\)
\(q[tt++]=?\) 表示入队 \(q[++hh]=?\) 表示出队
\((3)\) 把入度为 \(0\) 的都入队,弹出队头元素,遍历其所有连接的节点,删除连接的边(即\(d[j]--\)),即只要 \(d[j]==0\) 把其压入队列
\((4)\) return \(tt-n\)
如果存在环,不会进入队列,则 \(tt-n<0\)
完整代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int M=2*N;
int h[N],e[M],ne[M],idx,d[N],q[N],n,m;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool topsort()
{
int hh=0,tt=0;
for(int i=1;i<=n;i++)
{
if(d[i]==0)
q[tt++]=i;
}
while(hh<tt)
{
int u=q[hh++];
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
d[j]--;
if(d[j]==0) q[tt++]=j;
}
}
return tt==n;
}
int main()
{
cin>>n>>m;
memset(d,0,sizeof d);
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
add(a,b);
d[b]++;
}
if(!topsort()) cout<<-1;
else
{
for(int i=0;i<n;i++)
{
cout<<q[i]<<" ";
}
}
return 0;
}

浙公网安备 33010602011771号