图论_搜索(更新中)

[图的搜索]
 

[图的dfs]
1.思想:stack + 搜索
图的深度搜索原理简析:
(1)搜索一个顶点,然后从这个顶点往下搜索,直到叶子结点(或已搜索标记结点)
(2)退回,查看当前结点是否有其余子结点,若有继续(1)
相当于stack,先推入一个顶点,然后查询是否有子结点,一直推入stack中,到叶子结点(或已搜索标记结点)
则弹出,并查询该结点是否有其余子结点,继续推入,直到所有顶点均入stack过。
2.代码实现:
#include "bits/stdc++.h"
using namespace std;
const int MAX_V = 1e4 + 5;
vector<int> G[MAX_V];//邻接表G
bool vis[MAX_V];//visited[]表示是否访问过该顶点
void dfs(int s)
{
vis[s] = true;
printf("%d ",s);
for (int u = 0; u < (int)G[s].size(); ++u)
{
if (vis[G[s][u]] == false)
dfs(G[s][u]);
}
}
int V,E;
int main()
{
scanf("%d%d",&V,&E);
for (int i = 1; i <= E; ++i)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
}
dfs(1);
}
3.注解:这段代码只适用于连通图,对于非连通图,建议查看bfs代码实现部分,可以参考实现。

[图的bfs]
1.思想:queue + 搜索
图的宽度搜索简析:
(1)搜索一个顶点,将该顶点加入queue中
(2)弹出queue队头元素,搜索以该结点为头的子结点,推入queue中
(3)重复(2)直到所有顶点均已查询过
2.代码实现
#include <iostream>
#include <queue>
const int MAX_N = 10;
using namespace std;
bool edge[MAX_N][MAX_N];
int vis[MAX_N];
queue<int> q;
int n,m;
void bfs(int s)
{
q.push(s);
vis[s] = true;
while (!q.empty())
{
int front = q.front();
cout << front << " ";
q.pop();
for (int u = 1; u <= n; ++u)
{
if (!vis[u] && true == edge[front][u])
{
vis[u] = true;
q.push(u);
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i = 1; i <= m; ++i)
{
int u,v;
scanf("%d%d",&u,&v);
edge[u][v] = true;
}
for (int i = 1; i <= n; ++i)
{
if (vis[i] == true)
continue;
bfs(i);
}
return 0;
}
3.样例提供,包括前面的图的dfs均可使用
样例说明:第一行表示 n顶点数 m边数
第二行起 m行表示哪两个点相连
(注:可以为无向图,也可以为有向图,不影响搜索结果)
n m
u1 v1
u2 v2
...
um vm

样例一:
9 10
1 2
3 4
3 5
3 6
3 7
4 8
5 8
7 8
6 9
7 9

样例二:
7 6
1 2
1 4
2 5
2 7
7 3
5 6


引入部分:
[完全图]
完全图分为无向完全图与有向完全图
(1)无向完全图:对于一个无向完全图,其中每对不同的顶点之间都恰连有一条边相连。
n个顶点的无向完全图表示为Kn; Kn.edge = n*(n - 1)/2;
(2)有向完全图:对于一个有向完全图,其中每对不同的顶点之间都恰连有两条边相互指向。
n个顶点的有向完全图表示为Kn; Kn.edge = n*(n - 1);
(注:无向完全图 ∈ 无向连通图)

[图着色问题]
图着色问题分为图的着色判定问题与图的着色优化问题
(1)图的着色判定问题:对于一个给定的无向连通图G和m种不同的颜色。用这些颜色给G中各顶点
着色,每一个顶点着一种颜色,是否有一种着色法使G中任意相邻的2个顶点有着不同的颜色?
(2)图的着色优化问题:对于一个给定的无向连通图G,问最少需要m种颜色对其进行图色使G中,
各个顶点两两不同颜色。其中m称为该图的最下着色数。

例题:
二分图判定
给定一个具有n(1 <= n <= 1000)个顶点的无向连通图。要给图中每个顶点染色,并且要使相邻顶点颜色不同。问是否最多用2种
颜色对其完成染色?(题目保证无重边或自环)
 1 const int maxn = 1005;
 2 vector<int> G[maxn];//邻接表建图
 3 int n;//顶点数
 4 int color[maxn];//顶点i的颜色 (1 or -1 表示染色所用的两种颜色,0表示未染色)
 5 
 6 //对图进行dfs,把顶点i染色(1 or -1)
 7 bool dfs(int v, int c)
 8 {
 9     color[v] = c;
10     for (int i = 0; i < G[v].size(); ++i)
11     {
12         //如果相邻顶点已经染色,并且相同,则返回false
13         if (color[G[v][i]] == c) 
14             return false; 
15         //如果相邻顶点还未被染色,则将其染色为-c
16         //如果将其染色为-c后,!dfs即与已染色点矛盾,则返回false
17         if (color[G[v][i]] == 0 && !dfs(G[v][i],-c)) return false;
18     }
19     //如果所有点均已染色,则返回true
20     return true;
21 }
22 
23 void solve()
24 {
25     for (int i = 1; i <= n; ++i)
26         if (color[i] == 0)
27             if (!dfs(i,1))
28             {
29                 printf("NO\n");
30                 return;
31             }
32     return printf("YES\n");
33 }
总结:
1.若题目未给定连通,有可能图是不连通的,此时上述dfs不能一次遍历所有顶点,需要对dfs进行些修改或者外部对多个图进行遍历。
2.图染色问题,一般使用dfs来解决
posted @ 2021-07-21 17:21  QingHUIWuHan  阅读(115)  评论(0)    收藏  举报