图论算法(邻接矩阵)
文章目录
图的创建
#define INF INT_MAX
template<typename T>
class Graph
{
private:
struct Node
{
//存储顶点信息
T value;
//存储顶点索引
int index;
};
//顶点数组
vector<Node>Vert;
//矩阵
vector<vector<int>>Matrix;
//顶点数
int vertnum;
//边数
int edgenum;
public:
Graph()
{
this->vertnum = this->edgenum = 0;
}
//通过顶点信息获得对应的索引值
pair<int, int>Locate(const T& val1, const T& val2)
{
int m, n;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == val1)
m = i;
if (Vert[i].value == val2)
n = i;
}
return make_pair(m, n);
}
void CreateGraph()
{
cout << "请输入顶点数:";
cin >> this->vertnum;
Vert.resize(this->vertnum);
Matrix.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
{
cout << "请输入第" << i + 1 << "个顶点信息:";
cin >> Vert[i].value;
Matrix[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
{
if (i == j)
Matrix[i][j] = 0;
else
Matrix[i][j] = INF;
}
}
cout << "请输入边数:";
cin >> this->edgenum;
T val1, val2;
int distance;
for (int i = 0; i < this->edgenum; i++)
{
cout << "请输入要连接的顶点:";
cin >> val1 >> val2;
pair<int, int>ret = Locate(val1, val2);
cout << "请输入边长:";
cin >> distance;
Matrix[ret.first][ret.second] = distance;
//若为无向图,添加下面这一条代码
//Matrix[ret.second][ret.first] = distance;
}
}
void Print()
{
cout << " ";
for (int i = 0; i < this->vertnum; i++)
cout << setw(3)<<Vert[i].value << " ";
cout << endl;
for (int i = 0; i < this->vertnum; i++)
{
cout << setw(3) << Vert[i].value << " ";
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] == INF)
cout << setw(3) << "oo" << " ";
else
cout << setw(3) << Matrix[i][j] << " ";
}
cout << endl;
}
}
};
拓扑排序
打印入度为0的顶点,然后将该顶点去除,重复上述操作
void Tology()
{
cout << "拓扑排序:";
//记录每个节点的入度
vector<int>In;
In.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
In[j]++;
}
}
//队列
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
//入度为0,则入队列
if (In[i] == 0)
{
q.push(i);
cout << Vert[i].value << " ";
break;
}
}
while (!q.empty())
{
int top = q.front();
q.pop();
//更新各个顶点的入度
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
In[i]--;
if (In[i] == 0)
{
cout << Vert[i].value << " ";
q.push(i);
}
}
}
}
cout << endl;
}
无权最短路径
使用DFS算法,不考虑边长,获得各个顶点到起点的距离
//打印路径
void print_path(vector<int>& pre, int x)
{
if (x == pre[x])
{
cout << Vert[x].value << " -> ";
return;
}
print_path(pre, pre[x]);
cout << Vert[x].value << " -> ";
}
void NoWeight()
{
cout << "请输入起点:";
T start;
cin >> start;
//记录距离的数组
vector<int>dist;
//用于判断是否已入队
vector<int>visit;
vector<int>pre;
dist.resize(this->vertnum, -1);
visit.resize(this->vertnum, 0);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
visit[i] = 1;
q.push(i);
break;
}
}
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
//更新dist数组
if (visit[i] == 0)
{
dist[i] = dist[top] + 1;
visit[i] = 1;
pre[i] = top;
q.push(i);
}
}
}
}
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre,i);
cout << "end"<<endl;
}
}
Dijkstra算法
具体理论可看以下链接:
Dijkstra算法原理(转自平凡的L同学)
void Dijkstra()
{
T start;
cout << "请输入起点:";
cin >> start;
vector<int>dist;
vector<int>visit;
vector<int>pre;
dist.resize(this->vertnum, INF);
visit.resize(this->vertnum, 0);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
visit[i] = 1;
q.push(i);
break;
}
}
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
//更新dist数组
if (dist[top] + Matrix[top][i] < dist[i])
{
dist[i] = dist[top] + Matrix[top][i];
pre[i] = top;
//判断是否入队
if (visit[i] == 0)
{
visit[i] = 1;
q.push(i);
}
}
}
}
}
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre, i);
cout << "end" << endl;
}
}
Floyd算法
获得每个顶点到其他顶点的距离
最短路径模板+解析(Floyd算法)(转自coderyzh)
void Floyd()
{
vector<vector<int>>capacity;
capacity.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
{
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
capacity[i][j] = Matrix[i][j];
}
//判断是否存在从i到k再从k到j的路径,使capacity[i][j]变小
for (int k = 0; k < this->vertnum; k++)
{
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (capacity[i][k] != INF && capacity[k][j] != INF && capacity[i][k] + capacity[k][j] < capacity[i][j])
{
capacity[i][j] = capacity[i][k] + capacity[k][j];
}
}
}
}
cout << " ";
for (int i = 0; i < this->vertnum; i++)
cout << setw(3) << Vert[i].value << " ";
cout << endl;
for (int i = 0; i < this->vertnum; i++)
{
cout << setw(3) << Vert[i].value << " ";
for (int j = 0; j < this->vertnum; j++)
{
if (capacity[i][j] == INF)
cout << setw(3) << "oo" << " ";
else
cout << setw(3) <<capacity[i][j] << " ";
}
cout << endl;
}
}
Bellman_Ford算法
获得存在负值边的图的最短路径
图算法:2、计算带有负权值的单源最短路径:Bellman-Ford算法(转自天地一扁舟)
第一个图有负回路,第二个图无负回路
void Bellman_Ford()
{
vector<int>dist;
vector<int>pre;
dist.resize(this->vertnum, INF);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
T start;
cout << "请输入起点:";
cin >> start;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
break;
}
}
//松弛操作
for (int k = 0; k < this->vertnum - 1; k++)
{
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
{
if (dist[i] + Matrix[i][j] < dist[j])
{
pre[j] = i;
dist[j] = dist[i] + Matrix[i][j];
}
}
}
}
}
bool flag = false;
//松弛操作后,若还能松弛,则说明肯定存在负回路
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
{
if (dist[i] + Matrix[i][j] < dist[j])
{
flag = true;
break;
}
}
}
if (flag)
break;
}
if (flag)
cout << "存在负环路" << endl;
else
{
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre, i);
cout << "end" << endl;
}
}
}
SPFA算法
获得存在负值边的图的最短路径,与Bellman_Ford算法类似,但使用队列对Bellman_Ford进行改进
最短路径问题—SPFA算法详解(转自Ouyang_Lianjun
)
void SPFA()
{
vector<int>dist;
vector<int>pre;
//记录入队次数
vector<int>count;
dist.resize(this->vertnum, INF);
pre.resize(this->vertnum);
count.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
T start;
cout << "请输入起点:";
cin >> start;
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
count[i]++;
q.push(i);
break;
}
}
bool flag = false;
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (dist[top] + Matrix[top][i] < dist[i])
{
dist[i] = dist[top] + Matrix[top][i];
pre[i] = top;
count[i]++;
q.push(i);
//入队次数等于顶点数时,说明存在负回路
if (count[i] == this->vertnum)
{
flag = true;
break;
}
}
}
}
if (flag)
break;
}
if (flag)
cout << "存在负环路" << endl;
else
{
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre, i);
cout << "end" << endl;
}
}
}
Prim算法
生成最小树的一种方法
最小生成树Prim算法理解(转自qwurey)
void Prim()
{
T start;
cout << "请输入起点:";
cin >> start;
vector<int>dist;
vector<int>pre;
dist.resize(this->vertnum, INF);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
int top = 0;
int count = 0;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = -1;
top = i;
count++;
break;
}
}
int ans = 0;
while (count < this->vertnum)
{
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i]!=-1&&Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (Matrix[top][i] < dist[i])
{
dist[i] = Matrix[top][i];
pre[i] = top;
}
}
}
int minz = INF;
int nextpos;
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] != -1 && dist[i] < minz)
{
minz = dist[i];
nextpos = i;
}
}
if (minz == INF)
break;
else
{
cout << Vert[pre[nextpos]].value << " -- " << Vert[nextpos].value << ":" << minz << endl;
ans += minz;
top = nextpos;
dist[top] = -1;
count++;
}
}
cout << ans << endl;
}
Kruskal算法
生成最小树的一种方法,运用到并查集的知识
最小生成树(kruskal算法)(转自Superb_Day
)
//并查集查找和合并操作
int Find(vector<int>& pre, int x)
{
if (x == pre[x])
return x;
int root = x;
while (root != pre[root])
root = pre[root];
int j = x;
while (j != root)
{
int k = pre[j];
pre[j] = root;
j = k;
}
return root;
}
bool Union(vector<int>& pre, int root1, int root2)
{
root1 = Find(pre, root1);
root2 = Find(pre, root2);
if (root1 == root2)
return false;
pre[root1] = root2;
return true;
}
void Kruskal()
{
struct node
{
int from;
int to;
int distance;
};
//定义排序方式
struct cmp
{
bool operator()(node a, node b)
{
return a.distance > b.distance;
}
};
//优先队列,根据距离排序,队列最前面的是距离最小的
priority_queue<node, vector<node>, cmp>q;
vector<int>pre;
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = i;
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
{
node pnew;
pnew.from = i;
pnew.to = j;
pnew.distance = Matrix[i][j];
q.push(pnew);
}
}
}
int ans = 0;
while (!q.empty())
{
node top = q.top();
q.pop();
if (Union(pre, top.from, top.to))
{
ans += top.distance;
cout << Vert[top.from].value << " -- " << Vert[top.to].value << ":" << top.distance << endl;
}
bool flag = false;
for (int i = 1; i < this->vertnum; i++)
{
//判断是否有不再同一个集合的顶点,有的话继续进行合并
if (Find(pre, i) != Find(pre, 0))
{
flag = true;
}
}
if (!flag)
break;
}
cout << ans << endl;
}
DFS
图的深度搜索算法
图的广度优先搜索(BFS)和深度优先搜索(DFS)算法解析(转自Chida15)
void DFS()
{
T start;
cout << "请输入起点:";
cin >> start;
vector<int>visit;
visit.resize(this->vertnum, 0);
stack<int>s;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
visit[i] = 1;
s.push(i);
cout << Vert[i].value << " ";
break;
}
}
while (!s.empty())
{
int top = s.top();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
//判断是否已入队
if (visit[i] == 0)
{
s.push(i);
visit[i] = 1;
cout << Vert[i].value << " ";
break;
}
}
}
if (top == s.top())
s.pop();
}
cout << endl;
}
最大流之EK算法
求最大流的两种算法 EK算法和dinic算法(转自一枚研究生er)
//广度优先算法,先判断是否存在从起点到终点的路径
int bfs(vector<vector<int>>& capacity, vector<int>& pre, vector<int>& flow, int start, int end)
{
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = -1;
flow[i] = INF;
}
pre[start] = start;
queue<int>q;
q.push(start);
while (!q.empty())
{
int top = q.front();
q.pop();
if (top == end)
break;
for (int i = 0; i < this->vertnum; i++)
{
if (pre[i]==-1&&capacity[top][i] != 0 && capacity[top][i] != INF)
{
//更新流的长度
flow[i] = min(flow[top], capacity[top][i]);
pre[i] = top;
q.push(i);
}
}
}
if (pre[end] == -1)
return -1;
return flow[end];
}
void EK()
{
vector<vector<int>>capacity;
vector<int>pre;
vector<int>flow;
capacity.resize(this->vertnum);
pre.resize(this->vertnum);
flow.resize(this->vertnum, INF);
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = i;
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
{
capacity[i][j] = Matrix[i][j];
}
}
T start, end;
cout << "请输入起点和终点:";
cin >> start >> end;
pair<int, int>ret = Locate(start, end);
int increment = 0;
int ans = 0;
while (1)
{
increment = bfs(capacity, pre, flow, ret.first, ret.second);
if (increment == -1)
break;
ans += increment;
int k = ret.second;
while (k != ret.first)
{
capacity[pre[k]][k] -= increment;
capacity[k][pre[k]] += increment;
k = pre[k];
}
}
cout << ans << endl;
}
最大流之Dinic算法
求最大流的两种算法 EK算法和dinic算法(转自一枚研究生er)
//广度优先算法,计算每个顶点到起点的无变最短路径
bool bfs1(vector<vector<int>>& capacity, vector<int>& dist, int start, int end)
{
for (int i = 0; i < this->vertnum; i++)
dist[i] = -1;
dist[start] = 0;
queue<int>q;
q.push(start);
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] == -1 && capacity[top][i] != 0 && capacity[top][i] != INF)
{
dist[i] = dist[top] + 1;
q.push(i);
}
}
}
if (dist[end] == -1)
return false;
return true;
}
int dfs(vector<vector<int>>& capacity, vector<int>& dist, int now, int end, int value)
{
if (now == end)
return value;
int minz = INF;
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] == dist[now] + 1 && capacity[now][i] != 0 && capacity[now][i] != INF)
{
if (minz = dfs(capacity, dist, i, end, min(capacity[now][i], value)))
{
capacity[now][i] -= minz;
capacity[i][now] += minz;
return minz;
}
}
}
return 0;
}
void Dinic()
{
vector<vector<int>>capacity;
vector<int>dist;
capacity.resize(this->vertnum);
dist.resize(this->vertnum, -1);
for (int i = 0; i < this->vertnum; i++)
{
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
capacity[i][j] = Matrix[i][j];
}
T start, end;
cout << "请输入起点和终点:";
cin >> start >> end;
pair<int, int>ret = Locate(start, end);
int ans = 0;
while (bfs1(capacity, dist, ret.first, ret.second))
{
ans += dfs(capacity, dist, ret.first, ret.second, INF);
}
cout << ans << endl;
}
最大流之SAP算法
SAP是对Dinic算法的改进,通过增加一个层数组,当出现断层时,直接退出
网络流最大流的sap()算法(转自shiqi_614)
void SAP()
{
vector<vector<int>>capacity;
vector<int>gap;
vector<int>dist;
vector<int>pre;
vector<int>flow;
capacity.resize(this->vertnum);
gap.resize(this->vertnum, 0);
dist.resize(this->vertnum, -1);
pre.resize(this->vertnum);
flow.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = i;
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
capacity[i][j] = Matrix[i][j];
}
T start, end;
cout << "请输入起点和终点:";
cin >> start >> end;
pair<int, int>ret = Locate(start, end);
dist[ret.second] = 0;
queue<int>q;
q.push(ret.second);
gap[0]++;
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] == -1 && capacity[i][top] != 0 && capacity[i][top] != INF)
{
dist[i] = dist[top] + 1;
gap[dist[i]]++;
q.push(i);
}
}
}
if (dist[ret.first] == -1)
return;
int ans = 0;
int top = ret.first;
int i, j;
while (dist[ret.first] < this->vertnum)
{
bool flag = false;
flow[ret.first] = INF;
for (i = 0; i < this->vertnum; i++)
{
if (dist[i] + 1 == dist[top] && dist[i] >= 0 && capacity[top][i] != 0 && capacity[top][i] != INF)
{
flag = true;
break;
}
}
if (flag)
{
flow[i] = min(flow[top], capacity[top][i]);
pre[i] = top;
top = i;
if (top == ret.second)
{
ans += flow[ret.second];
int k = ret.second;
while (k != ret.first)
{
capacity[pre[k]][k] -= flow[ret.second];
capacity[k][pre[k]] += flow[ret.second];
k = pre[k];
}
top = ret.first;
for (int i = 0; i < this->vertnum; i++)
flow[i] = INF;
}
}
else
{
int minz = INF;
for (j = 0; j < this->vertnum; j++)
{
if (dist[j] + 1 < minz && dist[j] >= 0 && capacity[top][j] != 0 && capacity[top][j] != INF)
{
minz = dist[j] + 1;
}
}
gap[dist[top]]--;
if (gap[dist[top]] == 0)
break;
dist[top] = minz;
gap[minz]++;
if (top != ret.first)
top = pre[top];
}
}
cout << ans << endl;
}
void dfs(vector<vector<int>>& capacity, stack<int>& s, int start) {
for (int i = 0; i < this->vertnum; i++) {
if (capacity[start][i] != 0) {
capacity[start][i] = capacity[i][start] = 0;
s.push(i);
dfs(capacity, s, i);
break;
}
}
}
void Fleury(vector<vector<int>>& capacity, stack<int>& s, int start)
{
s.push(start);
while (!s.empty())
{
bool flag = false;
for (int i = 0; i < this->vertnum; i++)
{
if (capacity[s.top()][i] != 0)
{
flag = true;
break;
}
}
if (flag) {
dfs(capacity, s, s.top());
}
else {
cout << Vert[s.top()].value << " ";
s.pop();
}
}
}
欧拉回路
遍历每条边,如何回到起点的为欧拉回路;
遍历每条边的为欧拉路
void dfs(vector<vector<int>>& capacity, stack<int>& s, int start) {
for (int i = 0; i < this->vertnum; i++) {
if (capacity[start][i] != 0) {
capacity[start][i] = capacity[i][start] = 0;
s.push(i);
dfs(capacity, s, i);
break;
}
}
}
void Fleury(vector<vector<int>>& capacity, stack<int>& s, int start)
{
s.push(start);
while (!s.empty())
{
bool flag = false;
for (int i = 0; i < this->vertnum; i++)
{
if (capacity[s.top()][i] != 0)
{
flag = true;
break;
}
}
if (flag) {
dfs(capacity, s, s.top());
}
else {
cout << Vert[s.top()].value << " ";
s.pop();
}
}
}
void Euler() {
vector<vector<int>>capacity;
vector<int>In;
capacity.resize(this->vertnum);
In.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++) {
capacity[i].resize(this->vertnum, 0);
for (int j = 0; j < this->vertnum; j++) {
if (Matrix[i][j] != 0 && Matrix[i][j] != INF) {
capacity[i][j] = 1;
In[i]++;
In[j]++;
}
}
}
int num = 0;
for (int i = 0; i < this->vertnum; i++){
if (In[i] % 2 == 1)
num++;
}
if (num == 0 || num == 2) {
if (num == 0)
cout << "存在欧拉回路:" << endl;
else
cout << "存在欧拉路:" << endl;
T start;
cout << "请输入起点:";
cin >> start;
stack<int>s;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
Fleury(capacity, s, i);
break;
}
}
}
else
cout << "不存在欧拉路或欧拉回路" << endl;
}```
总结
#include<iostream>
using namespace std;
#include<string>
#include<queue>
#include<iomanip>
#include<stack>
#define INF INT_MAX
template<typename T>
class Graph
{
private:
struct Node
{
T value;
int index;
};
vector<Node>Vert;
vector<vector<int>>Matrix;
int vertnum;
int edgenum;
public:
Graph()
{
this->vertnum = this->edgenum = 0;
}
pair<int, int>Locate(const T& val1, const T& val2)
{
int m, n;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == val1)
m = i;
if (Vert[i].value == val2)
n = i;
}
return make_pair(m, n);
}
void CreateGraph()
{
cout << "请输入顶点数:";
cin >> this->vertnum;
Vert.resize(this->vertnum);
Matrix.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
{
cout << "请输入第" << i + 1 << "个顶点信息:";
cin >> Vert[i].value;
Matrix[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
{
if (i == j)
Matrix[i][j] = 0;
else
Matrix[i][j] = INF;
}
}
cout << "请输入边数:";
cin >> this->edgenum;
T val1, val2;
int distance;
for (int i = 0; i < this->edgenum; i++)
{
cout << "请输入要连接的顶点:";
cin >> val1 >> val2;
pair<int, int>ret = Locate(val1, val2);
cout << "请输入边长:";
cin >> distance;
Matrix[ret.first][ret.second] = distance;
Matrix[ret.second][ret.first] = distance;
}
}
void Print()
{
cout << " ";
for (int i = 0; i < this->vertnum; i++)
cout << setw(3)<<Vert[i].value << " ";
cout << endl;
for (int i = 0; i < this->vertnum; i++)
{
cout << setw(3) << Vert[i].value << " ";
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] == INF)
cout << setw(3) << "oo" << " ";
else
cout << setw(3) << Matrix[i][j] << " ";
}
cout << endl;
}
}
void Tology()
{
cout << "拓扑排序:";
vector<int>In;
In.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
In[j]++;
}
}
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (In[i] == 0)
{
q.push(i);
cout << Vert[i].value << " ";
break;
}
}
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
In[i]--;
if (In[i] == 0)
{
cout << Vert[i].value << " ";
q.push(i);
}
}
}
}
cout << endl;
}
void print_path(vector<int>& pre, int x)
{
if (x == pre[x])
{
cout << Vert[x].value << " -> ";
return;
}
print_path(pre, pre[x]);
cout << Vert[x].value << " -> ";
}
void NoWeight()
{
cout << "请输入起点:";
T start;
cin >> start;
vector<int>dist;
vector<int>visit;
vector<int>pre;
dist.resize(this->vertnum, -1);
visit.resize(this->vertnum, 0);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
visit[i] = 1;
q.push(i);
break;
}
}
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (visit[i] == 0)
{
dist[i] = dist[top] + 1;
visit[i] = 1;
pre[i] = top;
q.push(i);
}
}
}
}
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre,i);
cout << "end"<<endl;
}
}
void Dijkstra()
{
T start;
cout << "请输入起点:";
cin >> start;
vector<int>dist;
vector<int>visit;
vector<int>pre;
dist.resize(this->vertnum, INF);
visit.resize(this->vertnum, 0);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
visit[i] = 1;
q.push(i);
break;
}
}
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (dist[top] + Matrix[top][i] < dist[i])
{
dist[i] = dist[top] + Matrix[top][i];
pre[i] = top;
if (visit[i] == 0)
{
visit[i] = 1;
q.push(i);
}
}
}
}
}
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre, i);
cout << "end" << endl;
}
}
void Floyd()
{
vector<vector<int>>capacity;
capacity.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
{
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
capacity[i][j] = Matrix[i][j];
}
for (int k = 0; k < this->vertnum; k++)
{
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (capacity[i][k] != INF && capacity[k][j] != INF && capacity[i][k] + capacity[k][j] < capacity[i][j])
{
capacity[i][j] = capacity[i][k] + capacity[k][j];
}
}
}
}
cout << " ";
for (int i = 0; i < this->vertnum; i++)
cout << setw(3) << Vert[i].value << " ";
cout << endl;
for (int i = 0; i < this->vertnum; i++)
{
cout << setw(3) << Vert[i].value << " ";
for (int j = 0; j < this->vertnum; j++)
{
if (capacity[i][j] == INF)
cout << setw(3) << "oo" << " ";
else
cout << setw(3) <<capacity[i][j] << " ";
}
cout << endl;
}
}
void Bellman_Ford()
{
vector<int>dist;
vector<int>pre;
dist.resize(this->vertnum, INF);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
T start;
cout << "请输入起点:";
cin >> start;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
break;
}
}
for (int k = 0; k < this->vertnum - 1; k++)
{
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
{
if (dist[i] + Matrix[i][j] < dist[j])
{
pre[j] = i;
dist[j] = dist[i] + Matrix[i][j];
}
}
}
}
}
bool flag = false;
for (int i = 0; i < this->vertnum; i++)
{
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
{
if (dist[i] + Matrix[i][j] < dist[j])
{
flag = true;
break;
}
}
}
if (flag)
break;
}
if (flag)
cout << "存在负环路" << endl;
else
{
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre, i);
cout << "end" << endl;
}
}
}
void SPFA()
{
vector<int>dist;
vector<int>pre;
vector<int>count;
dist.resize(this->vertnum, INF);
pre.resize(this->vertnum);
count.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
T start;
cout << "请输入起点:";
cin >> start;
queue<int>q;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = 0;
count[i]++;
q.push(i);
break;
}
}
bool flag = false;
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (dist[top] + Matrix[top][i] < dist[i])
{
dist[i] = dist[top] + Matrix[top][i];
pre[i] = top;
count[i]++;
q.push(i);
if (count[i] == this->vertnum)
{
flag = true;
break;
}
}
}
}
if (flag)
break;
}
if (flag)
cout << "存在负环路" << endl;
else
{
for (int i = 0; i < this->vertnum; i++)
{
cout << Vert[i].value << " " << dist[i] << " ";
print_path(pre, i);
cout << "end" << endl;
}
}
}
void Prim()
{
T start;
cout << "请输入起点:";
cin >> start;
vector<int>dist;
vector<int>pre;
dist.resize(this->vertnum, INF);
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
pre[i] = i;
int top = 0;
int count = 0;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
dist[i] = -1;
top = i;
count++;
break;
}
}
int ans = 0;
while (count < this->vertnum)
{
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i]!=-1&&Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (Matrix[top][i] < dist[i])
{
dist[i] = Matrix[top][i];
pre[i] = top;
}
}
}
int minz = INF;
int nextpos;
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] != -1 && dist[i] < minz)
{
minz = dist[i];
nextpos = i;
}
}
if (minz == INF)
break;
else
{
cout << Vert[pre[nextpos]].value << " -- " << Vert[nextpos].value << ":" << minz << endl;
ans += minz;
top = nextpos;
dist[top] = -1;
count++;
}
}
cout << ans << endl;
}
int Find(vector<int>& pre, int x)
{
if (x == pre[x])
return x;
int root = x;
while (root != pre[root])
root = pre[root];
int j = x;
while (j != root)
{
int k = pre[j];
pre[j] = root;
j = k;
}
return root;
}
bool Union(vector<int>& pre, int root1, int root2)
{
root1 = Find(pre, root1);
root2 = Find(pre, root2);
if (root1 == root2)
return false;
pre[root1] = root2;
return true;
}
void Kruskal()
{
struct node
{
int from;
int to;
int distance;
};
struct cmp
{
bool operator()(node a, node b)
{
return a.distance > b.distance;
}
};
priority_queue<node, vector<node>, cmp>q;
vector<int>pre;
pre.resize(this->vertnum);
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = i;
for (int j = 0; j < this->vertnum; j++)
{
if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
{
node pnew;
pnew.from = i;
pnew.to = j;
pnew.distance = Matrix[i][j];
q.push(pnew);
}
}
}
int ans = 0;
while (!q.empty())
{
node top = q.top();
q.pop();
if (Union(pre, top.from, top.to))
{
ans += top.distance;
cout << Vert[top.from].value << " -- " << Vert[top.to].value << ":" << top.distance << endl;
}
bool flag = false;
for (int i = 1; i < this->vertnum; i++)
{
if (Find(pre, i) != Find(pre, 0))
{
flag = true;
}
}
if (!flag)
break;
}
cout << ans << endl;
}
void DFS()
{
T start;
cout << "请输入起点:";
cin >> start;
vector<int>visit;
visit.resize(this->vertnum, 0);
stack<int>s;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
visit[i] = 1;
s.push(i);
cout << Vert[i].value << " ";
break;
}
}
while (!s.empty())
{
int top = s.top();
for (int i = 0; i < this->vertnum; i++)
{
if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
{
if (visit[i] == 0)
{
s.push(i);
visit[i] = 1;
cout << Vert[i].value << " ";
break;
}
}
}
if (top == s.top())
s.pop();
}
cout << endl;
}
int bfs(vector<vector<int>>& capacity, vector<int>& pre, vector<int>& flow, int start, int end)
{
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = -1;
flow[i] = INF;
}
pre[start] = start;
queue<int>q;
q.push(start);
while (!q.empty())
{
int top = q.front();
q.pop();
if (top == end)
break;
for (int i = 0; i < this->vertnum; i++)
{
if (pre[i]==-1&&capacity[top][i] != 0 && capacity[top][i] != INF)
{
flow[i] = min(flow[top], capacity[top][i]);
pre[i] = top;
q.push(i);
}
}
}
if (pre[end] == -1)
return -1;
return flow[end];
}
void EK()
{
vector<vector<int>>capacity;
vector<int>pre;
vector<int>flow;
capacity.resize(this->vertnum);
pre.resize(this->vertnum);
flow.resize(this->vertnum, INF);
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = i;
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
{
capacity[i][j] = Matrix[i][j];
}
}
T start, end;
cout << "请输入起点和终点:";
cin >> start >> end;
pair<int, int>ret = Locate(start, end);
int increment = 0;
int ans = 0;
while (1)
{
increment = bfs(capacity, pre, flow, ret.first, ret.second);
if (increment == -1)
break;
ans += increment;
int k = ret.second;
while (k != ret.first)
{
capacity[pre[k]][k] -= increment;
capacity[k][pre[k]] += increment;
k = pre[k];
}
}
cout << ans << endl;
}
bool bfs1(vector<vector<int>>& capacity, vector<int>& dist, int start, int end)
{
for (int i = 0; i < this->vertnum; i++)
dist[i] = -1;
dist[start] = 0;
queue<int>q;
q.push(start);
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] == -1 && capacity[top][i] != 0 && capacity[top][i] != INF)
{
dist[i] = dist[top] + 1;
q.push(i);
}
}
}
if (dist[end] == -1)
return false;
return true;
}
int dfs(vector<vector<int>>& capacity, vector<int>& dist, int now, int end, int value)
{
if (now == end)
return value;
int minz = INF;
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] == dist[now] + 1 && capacity[now][i] != 0 && capacity[now][i] != INF)
{
if (minz = dfs(capacity, dist, i, end, min(capacity[now][i], value)))
{
capacity[now][i] -= minz;
capacity[i][now] += minz;
return minz;
}
}
}
return 0;
}
void Dinic()
{
vector<vector<int>>capacity;
vector<int>dist;
capacity.resize(this->vertnum);
dist.resize(this->vertnum, -1);
for (int i = 0; i < this->vertnum; i++)
{
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
capacity[i][j] = Matrix[i][j];
}
T start, end;
cout << "请输入起点和终点:";
cin >> start >> end;
pair<int, int>ret = Locate(start, end);
int ans = 0;
while (bfs1(capacity, dist, ret.first, ret.second))
{
ans += dfs(capacity, dist, ret.first, ret.second, INF);
}
cout << ans << endl;
}
void SAP()
{
vector<vector<int>>capacity;
vector<int>gap;
vector<int>dist;
vector<int>pre;
vector<int>flow;
capacity.resize(this->vertnum);
gap.resize(this->vertnum, 0);
dist.resize(this->vertnum, -1);
pre.resize(this->vertnum);
flow.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++)
{
pre[i] = i;
capacity[i].resize(this->vertnum);
for (int j = 0; j < this->vertnum; j++)
capacity[i][j] = Matrix[i][j];
}
T start, end;
cout << "请输入起点和终点:";
cin >> start >> end;
pair<int, int>ret = Locate(start, end);
dist[ret.second] = 0;
queue<int>q;
q.push(ret.second);
gap[0]++;
while (!q.empty())
{
int top = q.front();
q.pop();
for (int i = 0; i < this->vertnum; i++)
{
if (dist[i] == -1 && capacity[i][top] != 0 && capacity[i][top] != INF)
{
dist[i] = dist[top] + 1;
gap[dist[i]]++;
q.push(i);
}
}
}
if (dist[ret.first] == -1)
return;
int ans = 0;
int top = ret.first;
int i, j;
while (dist[ret.first] < this->vertnum)
{
bool flag = false;
flow[ret.first] = INF;
for (i = 0; i < this->vertnum; i++)
{
if (dist[i] + 1 == dist[top] && dist[i] >= 0 && capacity[top][i] != 0 && capacity[top][i] != INF)
{
flag = true;
break;
}
}
if (flag)
{
flow[i] = min(flow[top], capacity[top][i]);
pre[i] = top;
top = i;
if (top == ret.second)
{
ans += flow[ret.second];
int k = ret.second;
while (k != ret.first)
{
capacity[pre[k]][k] -= flow[ret.second];
capacity[k][pre[k]] += flow[ret.second];
k = pre[k];
}
top = ret.first;
for (int i = 0; i < this->vertnum; i++)
flow[i] = INF;
}
}
else
{
int minz = INF;
for (j = 0; j < this->vertnum; j++)
{
if (dist[j] + 1 < minz && dist[j] >= 0 && capacity[top][j] != 0 && capacity[top][j] != INF)
{
minz = dist[j] + 1;
}
}
gap[dist[top]]--;
if (gap[dist[top]] == 0)
break;
dist[top] = minz;
gap[minz]++;
if (top != ret.first)
top = pre[top];
}
}
cout << ans << endl;
}
void dfs(vector<vector<int>>& capacity, stack<int>& s, int start) {
for (int i = 0; i < this->vertnum; i++) {
if (capacity[start][i] != 0) {
capacity[start][i] = capacity[i][start] = 0;
s.push(i);
dfs(capacity, s, i);
break;
}
}
}
void Fleury(vector<vector<int>>& capacity, stack<int>& s, int start)
{
s.push(start);
while (!s.empty())
{
bool flag = false;
for (int i = 0; i < this->vertnum; i++)
{
if (capacity[s.top()][i] != 0)
{
flag = true;
break;
}
}
if (flag) {
dfs(capacity, s, s.top());
}
else {
cout << Vert[s.top()].value << " ";
s.pop();
}
}
}
void Euler() {
vector<vector<int>>capacity;
vector<int>In;
capacity.resize(this->vertnum);
In.resize(this->vertnum, 0);
for (int i = 0; i < this->vertnum; i++) {
capacity[i].resize(this->vertnum, 0);
for (int j = 0; j < this->vertnum; j++) {
if (Matrix[i][j] != 0 && Matrix[i][j] != INF) {
capacity[i][j] = 1;
In[i]++;
In[j]++;
}
}
}
int num = 0;
for (int i = 0; i < this->vertnum; i++){
if (In[i] % 2 == 1)
num++;
}
if (num == 0 || num == 2) {
if (num == 0)
cout << "存在欧拉回路:" << endl;
else
cout << "存在欧拉路:" << endl;
T start;
cout << "请输入起点:";
cin >> start;
stack<int>s;
for (int i = 0; i < this->vertnum; i++)
{
if (Vert[i].value == start)
{
Fleury(capacity, s, i);
break;
}
}
}
else
cout << "不存在欧拉路或欧拉回路" << endl;
}
};
int main()
{
Graph<int>g;
g.CreateGraph();
g.Print();
//g.Tology();
//g.NoWeight();
//g.Dijkstra();
//g.Floyd();
//g.Bellman_Ford();
//g.SPFA();
//g.Prim();
//g.Kruskal();
//g.DFS();
//g.EK();
//g.Dinic();
//g.SAP();
g.Euler();
return 0;
}