代码来源:晴神《算法笔记》!!
图的储存
-
邻接矩阵
略 -
邻接表
struct Node{
int v; //边的终点编号
int w; //边权
Node(int _v, int _w) : v(_v), w(_w) {} //构造函数
};
vector<Node> Adj[N];
Adj[1].push_back(Node(3,4)); //添加边
图的遍历
1.DFS 版本
- 邻接矩阵
void dfs(int u, int depth){
vis[u] = true;
for(int v = 0; v < n; v++){
if(vis[v] == false && g[u][v] != inf)
dfs(v, depth + 1);
}
}
void dfstrave(){
for(int u = 0; u < n; u++){
if(vis[u] == false){
dfs(u,1);
}
}
}
- 邻接表
vector<int> Adj[maxn];
int n;
bool vis[maxn] = {false};
void dfs(int u, int depth){
vis[u] = true;
for(int i = 0; i < Adj[u].size(); i++){
int v = Adj[u][i];
if(vis[v] == false)
dfs(v,depth + 1);
}
}
2.BFS版本
- 邻接矩阵
int n, g[maxn][maxn];
bool inq[maxn] = {false};
void bfs(int u){
queue<int> q;
q.push(u); //是push不是push_back
inq[u] = true;
while(!q.empty()){
int u = q.front(); //是front不是top
q.pop();
for(int v = 0; v < n; v++){
if(inq[v] ==false && g[u][v] != inf){
q.push(v);
inq[v] = true;
}
}
}
}
void bfstrave(){
for(int u = 0; u < n; u++){
if(inq[u] == false)
bfs(u);
}
}
- 邻接表
vector<int> Adj[maxn];
int n;
bool inq[maxn] = {false};
void bfs(int u){
queue<int> q;
q.push(u);
inq[u] = true;
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = 0; i < Adj[u].size(); i++){
int v = Adj[u][i];
if(inq[v] == false){
q.push(v);
inq[v] = true;
}
}
}
}
最短路径
Dijkstra算法
边权非负
- 伪代码
//s起点
dijkstra(g,d[],s){
初始化;
for(循环n次){
u = d[u]最小的还未访问的顶点标号;
记u被访问;
for(从u出发能到达的顶点v){
if(v未访问&&以u为中介点可以更新d[v]){
优化d[v];
//令v的前缀为u
}
}
}
}
- 邻接表
struct Node{
int v,dis;//dis为边权
};
vector<Node> Adj[maxn];
int n;
int d[maxn];
bool vis[maxn] = {false};
void dijkstra(int s){
fill(d, d + maxn, inf);
d[s] = 0;
for(int i = 0; i < n; i++){
int u = -1, MIN = inf;
for(int j = 0; j < n; j++){
if(vis[j] == false && d[j] < MIN){
MIN = d[j];
u = j;
}
}
if(u == -1) return;
vis[u] = true;
for(int j = 0; j < Adj[u].size(); j++){
int v = Adj[u][j].v;
if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
d[v] = d[u] + Adj[u][j].dis;
//pre[v] = u;
}
}
}
}
- 打印最短路径
void dfs(int s, int v){
if(v == s){
printf("%d\n",s);
return;
}
dfs(s,pre[v]);
printf("%d\n",v);
}
- 增加第二标尺(边权、点权、最短路径条数)
//增加边权,cost[u][v],c[] 初始时c[s]为0,其余为inf
for(int v = 0; v < n; v++){
if(vis[v] == false && g[u][v] != inf){
if(d[u] + g[u][v] < d[v]){
d[v] = d[u] + g[u][v];
c[v] = c[u] + cost[u][v];
}
else if(d[u] + g[u][v] == d[v] && c[u] + cost[u][v] < c[v]){
c[v] = c[u] + cost[u][v];
}
}
}
//增加点权,weight[u],w[] 初始时w[s]为weight[s],其余为0 略
//最短路径条数,num[] 初始时只有num[s]为1,其余为0
for(int v = 0; v < n; v++){
if(vis[v] == false && g[u][v] != inf){
if(d[u] + g[u][v] < d[v]){
d[v] = d[u] + g[u][v];
num[v] = num[u];
}
else if(d[u] + g[u][v] == d[v]){
num[v] += num[u];
}
}
}
- Dijkstra+DFS
//Dijkstra
//int pre[maxn]修改为vector<int> pre[maxn]或set<int> pre[maxn]
if(d[u] + g[u][v] < d[v]){
d[v] = d[u] + g[u][v];
pre[v].clear();
pre[v].push_back(u);
}
else if(d[u] + g[u][v] == d[v]){
pre[v].push_back(u);
}
//DFS
int optvalue;
vector<int> path, temppath;
void dfs(int v){
if(v == dt){
temppath.push_back(v);
int value;
计算value值; //倒着计算
if(value优于optvalue){
optvalue = value;
path = temppath;
}
temppath.pop_back();
return ;
}
temppath.push_back(v);
for(int i = 0; i < pre[v].size(); i++){
dfs(pre[v][i]);
}
temppath.pop_back();
}