寒假训练 第十节 搜索与图论 总结

图是由一个非空的顶点集合和一个描述顶点之间关系即边(Edges)的有限集合组成的一种数据结构。

图的相关术语

无向图
有向图
无向完全图
有向完全图
顶点的度、入度、出度、
权
网
路径、路径长度、
回路或环
简单路径
简单回路
稀疏图
子图
连通图
强连通图
生成树

图的遍历

深度优先算法
广度优先算法

深度优先算法

深度优先搜索遍历类似于树的先(根)序遍历,是树的先(根)序遍历的推广。

1.深度优先搜索的方法
(1)首先从图中某个顶点v出发,访问此顶点,将其标记为已访问过;
(2)然后从v的邻接链表中依次序选择第一个未被访问的邻接点w出发,按步骤(1)继续进行深度优先搜索;
(3)直到与当前顶点相连的所有邻接点都被访问到;
(4)若此时图中还有其他顶点未被访问,回溯到上一个起始顶点,重复步骤(2),直至图中所有顶点被访问。

#include 
//访问标志数组
int visited[MAX] = {0};

//用邻接表方式实现深度优先搜索(递归方式)
//v 传入的是第一个需要访问的顶点
void DFS(MGraph G, int v)
{
    //图的顶点的搜索指针
    ArcNode *p;
    //置已访问标记
    visited[v] = 1;
    //输出被访问顶点的编号
    printf("%d  ", v);
    //p指向顶点v的第一条弧的弧头结点
    p = G.vertices[v].firstarc;
    while (p != NULL)
    {
        //若p->adjvex顶点未访问,递归访问它
        if (visited[p->adjvex] == 0)
        {
            DFS(G, p->adjvex);
        }
        //p指向顶点v的下一条弧的弧头结点
        p = p->nextarc;
    }
}
广度优先算法

广度优先算法类似于树的按层次遍历

#include 
#include
using namespace std;

const int MAX = 10;
//辅助队列的初始化,置空的辅助队列Q,类似二叉树的层序遍历过程
queue<int> q;
//访问标记数组
bool visited[MAX];
//图的广度优先搜索算法
void BFSTraverse(Graph G, void (*visit)(int v))
{
    int v = 0;
    //初始化访问标记的数组
    for (v = 0; v < G.vexnum; v++)
    {
        visited[v] = false;
    }
    //依次遍历整个图的结点
    for (v = 0; v < G.vexnum; v++)
    {
        //如果v尚未访问,则访问 v
        if  (!visited[v])
        {
            //把 v 顶点对应的数组下标处的元素置为真,代表已经访问了
            visited[v] = true;
            //然后v入队列,利用了队列的先进先出的性质
            q.push(v);
            //访问 v,打印处理
            cout << q.back() << " ";
            //队不为空时
            while (!q.empty())
            {
                //队头元素出队,并把这个出队的元素置为 u,类似层序遍历
                Graph *u = q.front();
                q.pop();
                //w为u的邻接顶点
                for (int w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G,u,w))
                {
                    //w为u的尚未访问的邻接顶点
                    if (!visited[w])
                    {
                        visited[w] = true;
                        //然后 w 入队列,利用了队列的先进先出的性质
                        q.push(w);
                        //访问 w,打印处理
                        cout << q.back() << " ";
                    }//end of if
                }//end of for
            }//end of while
        }//end of if
    }// end of for
}

P1746 离开中山路

#include
#include
using namespace std;
struct date
{
	int x,y,sp;
}aaa;
int n,ans=1e9,x1,y1,x2,y2,g[10000][10000],arr1[4]={0,1,0,-1},arr2[4]={1,0,-1,0};
queue<date> q;
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			char x;
			cin>>x;
			g[i][j]=x-'0';
			}	
	cin>>x1>>y1>>x2>>y2;
	aaa.x=x1,aaa.y=y1,aaa.sp=0;
	q.push(aaa);
	g[x1][y1]=1;
	while(!q.empty())
	{
		date now=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			aaa.x=now.x+arr1[i];
			aaa.y=now.y+arr2[i];
			aaa.sp=now.sp+1;
			if(aaa.x==x2&&aaa.y==y2)
			{
					cout<<aaa.sp<<endl;
					return 0;
			}	
			if(aaa.x>=1&&aaa.x<=n&&aaa.y>=1&&aaa.y<=n&&g[aaa.x][aaa.y]==0)
			{
				g[aaa.x][aaa.y]=1;
				q.push(aaa);
			}
		}
	}
}

P1706 全排列问题

#include
#include
#include
#define MAX 10
using namespace std;
bool arr1[MAX];
int arr2[MAX],n;

void out() {
    for (int i = 1; i <= n; i++)
        printf("%5d", arr2[i]);
    printf("\n");
}

void dfs(int cnt) {
    if (cnt == n) {
        out(); return;
    }
    for (int i = 1; i <= n; i++) {
        if (arr1[i] == false)
        {
            arr1[i] = true;
            cnt++;
            arr2[cnt] = i;
            dfs(cnt);
            cnt--;
            arr1[i] = false;
        }
    }
}

int main() {
    cin >> n;
    dfs(0);
    return 0;
}

P2404 自然数的拆分问题

#include 
#include 
using namespace std;
int arr[10000]={1},n;
void dfs(int u,int t){
   if(u==0){
       for(int i=1;i<=t-2;i++){
           printf("%d+",arr[i]);
       }
       cout<<arr[t-1]<<"\n";
       return;
   }
   for(int i=arr[t-1];i<=u;i++){
       if(i<n){
           arr[t]=i;
           u-=i;
           dfs(u,t+1);
           u+=i;
       }
   }
}
int main(){
    cin>>n;
    dfs(n,1);
    return 0;

}

P1605 迷宫

#include
#include
using namespace std;
int n,m,b[5000][5000],x1,y_1,x2,y2,k;
int a[5000][5000],ans=0;
int bo=0;
void dfs(int i,int j) {
    if(b[i][j]==1)return;
    if(i<=0||i>n||j<=0||j>m) return;

    if(i==x2&&j==y2) {
        ans++;
		return;
    }

    b[i][j]=1;
    dfs(i+1,j);
    dfs(i-1,j);
    dfs(i,j-1);
    dfs(i,j+1);
    b[i][j]=0;
}

int main() {
    cin >> n >> m>>k>>x1>>y_1>>x2>>y2;
    int x,y;
    while(k--) {
        int x,y;
        cin >>x>>y;
        b[x][y]=1; 
    }
    dfs(x1,y_1);
    cout << ans ;
    return 0;
}

你可能感兴趣的:(图论,算法,深度优先)