【算法】图论学习笔记与代码实现

这学期两门主课 算法设计与分析(Algorithm and Analysis,ADA) 图论与算法(Graph Theory and Algorithms, GTA) 都涉及到很多经典图论问题以及相关代码实现,遂写下此文,以记录学习过程,随缘更新。


深度优先遍历(经典DFS):

从图中某一个节点出发,如果有未探索的邻居节点,则选择其中应该进行深入探索(其他节点暂时不管),每到一个新的节点则递归进行上述过程。当探索无法继续时(当前节点的所有邻居都在前面的探索过程中被标记过),则沿原路径回退。回退到某个节点时,若它还有其他的邻居节点没有探索,则继续深入探索。

使用白色,黑色,灰色记录每个节点的状态:

白色:表示一个节点尚未被遍历;

灰色:表示一个节点已经被遍历到,但是对于它的遍历尚未结束;即该节点还有若干邻居节点等待遍历,而当前算法正在递归处理其中一个邻居节点;

黑色:表示一个节点的所有邻居已经完成遍历,其自身的遍历也结束。

框架代码(包括封装和实现两部分):

具体实现(根据DFS遍历顺序简单输出一下各个节点的编号):

// DFS
#include 
#define N 10000
using namespace std;int graph[N][N];
int color[N]; // 0 white, 1 grey, 2 black
int n, m;void dfs(int v)
{color[v] = 1;for (int i = 1; i <= n; i++){if (i != v && graph[v][i] == 1){if (color[i] == 0){dfs(i);}}}cout << v << " ";color[v] = 2;
}void my_dfs()
{for (int i = 1; i <= n; i++){if (color[i] == 0)dfs(i);}cout << endl;
}int main()
{cin >> n >> m;for (int i = 0; i < m; i++){int x, y;cin >> x >> y;graph[x][y] = 1;}my_dfs();return 0;
}/*
input:
7 13
1 2
1 3
1 6
2 3
2 4
4 1
4 3
5 3
5 7
6 1
6 3
7 4
7 5output:
3 4 2 6 1 7 5 
*/

广度优先遍历(BFS):

从图中某个节点出发,首先处理该节点指向邻居的所有边,然后将所有邻居放入一个调度器——队列(queue)中,接着处理该节点。下一个遍历的节点从当前被发现但未被处理的点中选出,即队列的首个节点,然后将其邻居节点依次放入队尾,处理该节点自身。重复以上过程,直到队列为空,所有节点均被处理完毕。

仍然以上面的图为例,输出BFS顺序遍历每个节点的值:

// BFS
#include 
#include 
#define N 10000
using namespace std;int graph[N][N];
int color[N]; // 0 white, 1 grey, 2 black
int parent[N];
int dis[N];
int n, m;void bfs(int v)
{queue que;color[v] = 1; // greydis[v] = 0; // 源点que.push(v);while(!que.empty()){int w = que.front();que.pop();for (int i = 1; i < n; i++){if (i != w && graph[w][i] == 1){if (color[i] == 0){color[i] = 1; //greyparent[i] = w;dis[i] = dis[w] + 1;que.push(i);}}}cout << w << " ";color[w] = 2; // black}
}void my_bfs()
{for (int i = 1; i <= n; i++){color[i] = 0;parent[i] = 0;dis[i] = 0;}for (int i = 1; i <= n; i++){if (color[i] == 0)bfs(i);}cout << endl;
}int main()
{cin >> n >> m;for (int i = 0; i < m; i++){int x, y;cin >> x >> y;graph[x][y] = 1;}my_bfs();return 0;
}/*
input:
7 13
1 2
1 3
1 6
2 3
2 4
4 1
4 3
5 3
5 7
6 1
6 3
7 4
7 5
output:
1 2 3 6 4 5 7
*/

网络中的最大流:

题目描述:

给定n个点,m条有向边,给定每条边的容量,求从点s到点t的最大流

输入:

第一行四个整数n,m,s,t。
接下来的m行,每行三个整数u,v,c,表示u到v,流量为c的一条边,

输出:

输出点s到点t的最大流。

样例输入 :

7 14 1 7
1 2 5
1 3 6
1 4 5
2 3 2
2 5 3
3 2 2
3 4 3
3 5 3
3 6 7
4 6 5
5 6 1
6 5 1
5 7 8
6 7 7

样例输出 :

14

提示:

1<=n<=100,1<=m<=5000,0<=c<=2147483647

#include 
#include 
using namespace std;const int N = 10001, E = 200001;int n, m, s, t; 
long long ans = 0;
long long cnt = 1, first[N], nxt[E], to[E], val[E];inline void addE(int u, int v, long long w) 
{to[++cnt] = v;val[cnt] = w;nxt[cnt] = first[u];first[u] = cnt;
}int dep[N], q[N], l, r;bool bfs() 
{ memset(dep, 0, (n + 1) * sizeof(int));q[l = r = 1] = s;dep[s] = 1;while (l <= r) {int u = q[l++];for (int p = first[u]; p; p = nxt[p]) {int v = to[p];if (val[p] and !dep[v]) { dep[v] = dep[u] + 1;q[++r] = v;}}}return dep[t];
}long long dfs(int u, long long in) 
{if (u == t)return in;long long out = 0;for (int p = first[u]; p and in; p = nxt[p]){int v = to[p];if (val[p] and dep[v] == dep[u] + 1) {long long res = dfs(v, min(val[p], in));val[p] -= res;val[p ^ 1] += res;in -= res;out += res;}}if (out == 0)dep[u] = 0;return out;
}int main() 
{cin >> n >> m >> s >> t;for (int i = 1; i <= m; i++) {int u, v;  long long w;cin >> u >> v >> w;addE(u, v, w);addE(v, u, 0);}while (bfs())ans += dfs(s, 1e18);cout << ans << endl;return 0;
}
/**************************************************************Problem: 1006User: 201830210Language: C++Result: 正确Time:56 msMemory:0 kb
****************************************************************/

二分图中的最大匹配问题:

题目描述:

给定一个二分图,其左部点的个数为n,右部点的个数为m,边数为e,求其最大匹配的边数。

左部点从1至n编号,右部点从1至m编号。

输入:

输入的第一行是三个整数,分别代表n,m,e。

接下来输入e行,每行两个整数u,v,表示存在一条连接左部点u和右部点v的边。

输出:

输出一个整数,代表二分图最大匹配的边数。

样例输入:

4 2 7
3 1
1 2
3 2
1 1
4 2
4 1
1 1

样例输出:

2

提示:

1<= n,m <=100

#include
#include
#include
#include
using namespace std;int n,m;
int cnt=2;
int alist[6000001];
struct data
{int v;int next;int value;
}edge[6000001];void add(int u,int v,int value)
{edge[cnt].v=v;edge[cnt].value=value;edge[cnt].next=alist[u];alist[u]=cnt++;return ;
}
int h[1000001];
int q[1000001];bool bfs()
{int x,next;memset(h,-1,sizeof(h));int head=0,tail=1;q[head]=1;h[1]=0;while(head


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部