1.图的种类:
a.有向图,无向图,加权有向图,加权无向图
b.连接两个顶点u,v的边记作e=(u,v)
c.不存在环的有向图称为DAG
2.图的邻接矩阵:
a.优点:可以通过M[u][v]直接引用边(u,v),因此只需要常数时间(O(1))即可确定顶点u和顶点v的关系;只要更改M[u][v]只就能完成边的添加与删除,简单且高效
b.缺点:消耗的内存空间等于顶点数的平方。如果图的边数较少,就会浪费较大量的内存;在同一个邻接矩阵中,只能记录顶点u到顶点v的一个关系
3.图的深度优先搜索:
a.定义:在图的搜索算法中,深度优先搜索采取的思路是尽可能地访问相邻顶点。设仍存在未搜索邻接边的顶点中最后一个被发现的顶点为v,那么深度优先搜索就是对此顶点的的邻接递归地进行搜索。当v的边全部搜索完毕后,程序沿发现v时所经过的边回溯,继续搜索前一顶点。搜索一直持续到发现当前起点可到达的所有顶点为止。如果仍有顶点未被发现,则选择其中编号最小的一个作为新起来继续探索。
深度优先搜索中需要记录:
d[v]:记录第一次访问v的时刻
f[v]:记录调查完v的邻接表的时刻
b.过程:
1)将最初访问的顶点压入栈
2)如果栈中仍有顶点,则循环进行下述操作:先访问栈顶部的顶点u,然后从当前的顶点u移动至顶点v时,将v入栈。如果当前顶点u不存在未访问的顶点,则将u从栈中删除
c.代码:
4.图的广度优先搜索:
a.定义:在广度优先搜索中,要想发现与起点s距离为k+1的顶点,首先要发现所有距离为k的顶点,因此可以求出起点到各顶点的最短矩离
b.要点:使用邻接矩阵实现的广度优先搜索中,由于要调查每个顶点是否与其他点相邻,所以不适用于规模较大的图
5.连通分量:
a.题目:输入SNS的朋友关系,判断从指定人物出发能否通过双向朋友链抵达指定人物
b.要点:使用邻接且来表示图,其优点是只需与边数成正比的内存空间,其缺点难以有效的删除边
c.代码:
a.有向图,无向图,加权有向图,加权无向图
b.连接两个顶点u,v的边记作e=(u,v)
c.不存在环的有向图称为DAG
2.图的邻接矩阵:
a.优点:可以通过M[u][v]直接引用边(u,v),因此只需要常数时间(O(1))即可确定顶点u和顶点v的关系;只要更改M[u][v]只就能完成边的添加与删除,简单且高效
b.缺点:消耗的内存空间等于顶点数的平方。如果图的边数较少,就会浪费较大量的内存;在同一个邻接矩阵中,只能记录顶点u到顶点v的一个关系
c.代码:
//
// Created by 叶子 on 2018/2/5.
// 邻接矩阵的表示
//
#include "iostream"
using namespace std;
static const int N = 100;
int main(){
int M[N][N];
int n,u,k,v;
cin >> n;
for ( int i = 0 ; i < n ; i ++){
for ( int j = 0 ; j < n ; j ++ ) M[i][j] = 0 ;
}
for ( int i = 0 ; i < n ; i ++){
cin >> u >> k;
u --;
for ( int j = 0 ; j < k ; j ++){
cin >> v;
v --;
M[u][v] = 1;
}
}
for ( int i = 0 ; i < n ; i ++){
for ( int j = 0 ; j < n ; j ++){
if ( j ) cout << " ";
cout << M[i][j];
}
cout << endl;
}
}
3.图的深度优先搜索:
a.定义:在图的搜索算法中,深度优先搜索采取的思路是尽可能地访问相邻顶点。设仍存在未搜索邻接边的顶点中最后一个被发现的顶点为v,那么深度优先搜索就是对此顶点的的邻接递归地进行搜索。当v的边全部搜索完毕后,程序沿发现v时所经过的边回溯,继续搜索前一顶点。搜索一直持续到发现当前起点可到达的所有顶点为止。如果仍有顶点未被发现,则选择其中编号最小的一个作为新起来继续探索。
深度优先搜索中需要记录:
d[v]:记录第一次访问v的时刻
f[v]:记录调查完v的邻接表的时刻
b.过程:
1)将最初访问的顶点压入栈
2)如果栈中仍有顶点,则循环进行下述操作:先访问栈顶部的顶点u,然后从当前的顶点u移动至顶点v时,将v入栈。如果当前顶点u不存在未访问的顶点,则将u从栈中删除
c.代码:
#include "iostream"
#include "stack"
using namespace std;
static const int N = 100;
static const int WHITE = 0;
static const int GRAY = 1;
static const int BLACK = 2;
int n,M[N][N];
int color[N],d[N],f[N],tt;
int nt[N];
int next(int u){
for ( int v = nt[u]; v < n ; v++){
nt[u] = v + 1;
if ( M[u][v] ) return v;
}
return -1;
}
void dfs_visit(int r){
for ( int i = 0 ; i < n ; i ++) nt[i] = 0 ;
stack<int> S;
S.push(r);
color[r] = GRAY;
d[r] = ++tt;
while( !S.empty() ){
int u = S.top();
int v = next(u);
if ( v != -1){
if ( color[v] == WHITE) {
color[v] = GRAY;
d[v] = ++tt;
S.push(v);
}
} else {
S.pop();
color[u] = BLACK;
f[u] = ++tt;
}
}
}
void dfs(){
for ( int i = 0 ; i < n ; i ++){
color[i] = WHITE;
nt[i] = 0;
}
tt = 0 ;
for ( int u = 0 ; u < n ; u ++){
if ( color[u] == WHITE ) dfs_visit(u);
}
for ( int i = 0 ; i < n ; i ++){
cout << i + 1 << " " << d[i] << " " << f[i] << endl;
}
}
int main(){
int u,k,v;
cin >> n;
for ( int i = 0 ; i < n ; i ++){
for ( int j = 0 ; j < n ; j ++) M[i][j] = 0;
}
for ( int i = 0 ; i < n ; i ++){
cin >> u >> k;
u--;
for ( int j = 0 ; j < k ; j ++){
cin >> v;
v --;
M[u][v] = 1;
}
}
dfs();
return 0;
}
4.图的广度优先搜索:
a.定义:在广度优先搜索中,要想发现与起点s距离为k+1的顶点,首先要发现所有距离为k的顶点,因此可以求出起点到各顶点的最短矩离
b.要点:使用邻接矩阵实现的广度优先搜索中,由于要调查每个顶点是否与其他点相邻,所以不适用于规模较大的图
c.代码:
//
// Created by 叶子 on 2018/2/5.
// 广度优先搜索
//
#include "iostream"
#include "queue"
using namespace std;
static const int N = 100;
static const int INFTY = ( 1 << 2);
int n,M[N][N];
int d[N];
void bfs(int s ){
queue<int> q;
q.push(s);
for ( int i = 0 ; i < n ; i ++) d[i] = INFTY;
d[s] = 0 ;
int u ;
while ( !q.empty()){
u = q.front();
q.pop();
for ( int v = 0 ; v < n ; v ++){
if ( M[u][v] == 0 ) continue;
if ( d[v] != INFTY ) continue;
d[v] = d[u] + 1;
q.push(v);
}
}
for ( int i = 0 ; i < n ; i ++){
cout << i +1 << " " << ( d[i] == INFTY ? ( -1) : d[i] ) << endl;
}
}
int main(){
int u,k,v;
cin >> n;
for ( int i = 0 ; i < n ; i ++){
for ( int j = 0 ; j < n ; j ++) M[i][j] = 0;
}
for ( int i = 0 ; i < n ; i ++){
cin >> u >> k;
u --;
for ( int j = 0 ; j < k ; j ++){
cin >> v;
v--;
M[u][v] = 1;
}
}
bfs(0);
return 0;
}
5.连通分量:
a.题目:输入SNS的朋友关系,判断从指定人物出发能否通过双向朋友链抵达指定人物
b.要点:使用邻接且来表示图,其优点是只需与边数成正比的内存空间,其缺点难以有效的删除边
c.代码:
//
// Created by 叶子 on 2018/2/5.
// 连通分量
//
#include "iostream"
#include "vector"
#include "stack"
using namespace std;
static const int MAX = 100000;
static const int NIL = -1;
int n ;
vector<int> G[MAX];
int color[MAX];
void dfs(int r,int c){
stack<int> S;
S.push(r);
color[r] = c;
while ( !S.empty()){
int u = S.top();
S.pop();
for ( int i = 0 ; i < G[u].size() ; i ++){
int v = G[u][i];
if ( color[v] == NIL){
color[v] = c;
S.push(v);
}
}
}
}
void assignColor(){
int id = 1;
for ( int i = 0 ; i < n ; i ++) color[i] = NIL;
for ( int u = 0 ; u < n ; u ++){
if ( color[u] == NIL) dfs(u,id++);
}
}
int main(){
int s,t,m,q;
cin >> n >> m;
for ( int i = 0 ; i < m ; i ++){
cin >> s >> t;
G[s].push_back(t);
G[t].push_back(s);
}
assignColor();
cin >> q;
for ( int i = 0 ; i < q ; i ++){
cin >> s >> t;
if ( color[s] == color[t] ){
cout << "yes" << endl;
}else{
cout << "no" << endl;
}
}
return 0;
}