搜索

 

1.深度优先搜索(DFS)
对于任意的一个图,有一点x,我们寻找与它连通的所有深度更深的点y(若没有,回到上一个点)。若y被访问过,回到x。反之,访问y。如此循环往复。
若x被访问过,则x的父节点也一定被访问过。每条边至多被访问2次,每个点至多被访问一次。

inline void dfs(int x){
int i;
vis[x]=1;
for(i=1;i<=n;i++){
if(mp[x][i]&&!vis[i]){
dfs(i);
}
}
}

 


使用DFS枚举已知集合的所有子集状态
对于一个元素a[i]有两种选择:选/不选。于是我们DFS求出来的树同时是一棵二叉树。先沿着选的方向到底,在一步步回溯,直到遍历结束。

inline void dfs(int x){
if(x>n){
//得到了一个子集 
return ;
}
s[++tot]=a[x];
dfs(x+1);
tot--;
dfs(x+1);
}
(5)DFS枚举1~n的全排列
inline void dfs(int x){
if(x>n){
//得到了一个排列
return ; 
}
int i;
for(i=1;i<=n;i++){
if(!used[i]){    //没有使用过 
p[x]=i;    
used[i]=1;    //标记使用 
dfs(x+1);
used[i]=0;    //清空,准备下一步 
}
}
}

DFS判断图中有无环
分析:判断环我们只要判断图中有无返祖边(后向边)即可。返祖边:两点u,v,且u->v。vis[v] = 1,说明v已经被访问,但其子孙后代还没有被访问完。而u又指向说明u就是v的子孙后代,u->v是一条后向边(返祖边)。

广度优先搜索(BFS)
运用了队列知识

void bfs(){
q[tl++]=s;    
while(hd!=tl){
x=q[hd++];    //弹队头 
for(i=1;i<=n;i++){
if(mp[x][i]&&!vis[i]){    //连通且没被访问 
q[tl++]=i;    //加队尾 
vis[i]=1;    //标记访问 
}
}
}
}

3.记忆化搜索(DFS优化)
省去了重复的部分,加速

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N 1000
#define M 1000
using namespace std;
int n,m;
int u,v,c;
int s,to[M],l[M],ne[M],pre[N];
void add(int u,int v,int c)    //加边函数,邻接表存储 
{
to[++s]=v;
l[s]=c;
ne[s]=pre[u];
pre[u]=s;
}
int f[N];
bool vi[N];
int cal(int k)
{
if(vi[k]) return f[k];
vi[k]=true;
for(int i=pre[k];i;i=ne[i])
{
int x=to[i];
f[k]=max(f[k],cal(x)+l[i]);
}
return f[k];
}
int main()
{
cin>>n>>m;
while(m--)
{
cin>>u>>v>>c;
add(u,v,c);
}
for(int i=1;i<=n;i++) cout<<i<<' '<<cal(i)<<endl;
return 0;
}

 

posted @ 2020-04-04 15:37  2333333333龖  阅读(90)  评论(0编辑  收藏  举报