/* 测试数据
5 7
1 2 12
1 4 18
1 3 16
2 3 2
3 4 4
5 2 22
4 5 10
*/
#include <iostream>
#include <cstring>
#include <queue>
#include<algorithm>
using namespace std;
typedef int VertexType;
const int maxSize = 50;
bool vis[maxSize];
int n, e; //n个村e条边
int f[maxSize];
int distances[maxSize];
int distant[maxSize][maxSize];
const int INF = 0x3f3f3f;
int path[maxSize]; //存储点到点需要经过哪些点
int fpath[maxSize][maxSize];
int *lowcost;
int *vset;
//定义邻接矩阵
typedef struct MGraph
{
int edges[maxSize][maxSize];
int n, e;
VertexType vex[maxSize];
}MGraph;
//定义邻接表
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
double info;
}ArcNode;
typedef struct VNode
{
int data;
ArcNode *firstarc;
}VNode;
typedef struct AGraph
{
VNode adjlist[maxSize];
int n, e;
}AGraph;
void DFSMGraph(MGraph adjacent, int v) //邻接矩阵DFS
{
cout << v << " ";
vis[v] = 1;
for(int i = 1; i <= n; i++)
{
if(vis[i] == 0 && adjacent.edges[v][i] != 0)
DFSMGraph(adjacent, i);
}
}
void DFSAGraph(AGraph adjacency, int v) //邻接表DFS
{
ArcNode *p;
vis[v] = 1;
cout << v << " ";
p = adjacency.adjlist[v].firstarc;
while (p != NULL)
{
if(vis[p->adjvex] == 0)
DFSAGraph(adjacency, p->adjvex);
p = p->nextarc;
}
}
void BFSMGraph(MGraph adjacent, int v) //邻接矩阵BFS
{
queue<int> q;
q.push(v);
cout << v << " ";
vis[v] = 1;
while(!q.empty())
{
int temp = q.front();
q.pop();
for(int i = 1 ; i <= n ; i++)
{
if(adjacent.edges[temp][i] != 0 && vis[i] == 0)
{
cout << i << " ";
vis[i] = 1;
q.push(i);
}
}
}
}
void BFSAGraph(AGraph adjacency, int v)//邻接表BFS
{
queue<int> q;
ArcNode *p;
cout << v << " ";
vis[v] = 1;
p = adjacency.adjlist[v].firstarc;
while(!q.empty())
{
int front = q.front();
q.pop();
while(p != NULL)
{
if(vis[p->adjvex] == 0)
{
cout << p->adjvex << " ";
vis[p->adjvex] = 1;
q.push(p->adjvex);
}
p = p->nextarc;
}
}
}
void dfsIsTree(MGraph adjacent, int v, int &count, int &side)
{
vis[v] = 1;
count ++;
for(int i = 1; i <= n; i++)
{
if(vis[i] == 0 && adjacent.edges[v][i] != 0)
{
vis[i] = 1;
side++;
dfsIsTree(adjacent, i, count, side);
}
}
}
bool GisTree(MGraph adjacent)
{
int count = 0, side = 0;
memset(vis, 0, sizeof(vis));
dfsIsTree(adjacent, 1, count, side);
if(count == n && side == n-1)
return true;
else
return false;
}
typedef struct Road
{
int a, b;
int distance;
}Road;
int getfather(int v)
{
return v == f[v] ? v:getfather(f[v]);
}
bool cmp(Road a, Road b)
{
return a.distance < b.distance;
}
void unions(int x, int y)
{
x = getfather(x);
y = getfather(y);
if(x != y)
f[x] = y;
}
void Kruskal(int distances[], Road road[])
{
int j = 0;
for(int i = 1; i <= e; i++)
{
int a = getfather(road[i].a);
int b = getfather(road[i].b);
if(a != b)
{
unions(a, b);
distances[++j] = road[i].distance;
}
}
distances[0] = j;
for(int i = 1; i <= n; i++)
f[i] = getfather(f[i]);
}
void Prim(MGraph adjacent, int *lowcost, int *vset, int v0)
{
int k;
lowcost[v0] = 0;
vset[0] = n;
lowcost[0] = n;
for(int i = 1; i <= vset[0]; i++)
{
vset[i] = 0;
lowcost[i] = adjacent.edges[v0][i] ;
}
vset[v0] = 1;
for(int i = 1; i <= n; i++)
{
int min = INF;
for(int j = 1; j <= n; j++)
{
if(vset[j] == 0 && lowcost[j] < min)
{
k = j;
min = lowcost[j];
}
}
vset[k] = 1;
for(int j = 1; j <= n; j++)
{
if(vset[j] == 0 && adjacent.edges[k][j] < lowcost[j])
lowcost[j] = adjacent.edges[k][j];
}
}
}
void printfPath(int path[], int a) //逆序输出路径
{
int stack1[maxSize], top = -1;
while(path[a] != -1)
{
stack1[++top] = a;
a = path[a];
}
stack1[++top] = a;
while( top != -1)
{
if(top == 0)
cout << stack1[top--] ;
else
cout << stack1[top--] << " -> ";
}
}
void Dijkstra(MGraph g, int v, int dist[], int path[]) //邻接表的 Dijsktra
{
for(int i = 1; i <= g.n; i++)
{
dist[i] = g.edges[v][i];
if( g.edges [v][i] < INF )
path[i] = v;
else
path[i] = -1;
}
vis[v] = 1;
path[v] = -1;
for(int i = 1; i <= g.n; i++)
{
int min1 = INF;
int k = -1; // 用来标记找到最小值
for(int j = 1; j <= g.n; j++)
{
if( !vis[j] && min1 > dist[j])
{
min1 = dist[j];
k = j;
}
}
vis[k] = 1;
for(int j = 1; j <= g.n; j++)
if( vis[j] == 0 && dist[j] > dist[k] + g.edges[k][j] )
{
path[j] = k;
dist[j] = dist[k] + g.edges[k][j];
}
}
for(int i = 1; i <= g.n; i++)
{
if(dist[i] == INF)
{
cout << v << " 到 " << i << " 没有通路 " << endl;
continue;
}
cout << "从顶点 " << v << " 到顶点 " << i << "的最短路径为:" ;
printfPath(path, i);
cout << " 路径长度为:" << dist[i] << endl;
}
}
void AGDijkstra(AGraph m, int v, int dist[], int path[]) //邻接表的Dijkstra
{
ArcNode *p;
p = m.adjlist[v].firstarc;
vis[v] = 1;
for(int i = 1; i <= m.n; i++)
{
dist[i] = INF;
path[i] = -1;
}
dist[v] = 0;
path[v] = -1;
int k = -1, min1 = INF;
while( p )
{
dist[p->adjvex] = p->info;
if( !vis[p->adjvex] && min1 > p->info)
{
min1 = p->info;
k = p->adjvex;
path[p->adjvex] = v;
}
p = p->nextarc;
}
while(1){
k = -1, min1 = INF;
for(int j = 1; j <= m.n; j++)
{
if( !vis[j] && min1 > dist[j])
{
min1 = dist[j];
k = j;
}
}
if(k == -1) break;
vis[k] = 1;
p = m.adjlist[k].firstarc;
while ( p ){
if( !vis[p->adjvex] && dist[p->adjvex] > dist[k] + p->info )
{
path[p->adjvex] = k;
dist[p->adjvex] = dist[k] + p->info;
}
p = p->nextarc;
}
}
for(int i = 1; i <= m.n; i++)
{
if(dist[i] == INF)
{
cout << v << " 到 " << i << " 没有通路 " << endl;
continue;
}
cout << "从顶点 " << v << " 到顶点 " << i << "的最短路径为:" ;
printfPath(path, i);
cout << " 路径长度为:" << dist[i] << endl;
}
}
void printfPath(int path[][maxSize], int u, int v)
{
if(path[u][v] == -1)
{
cout << v << " ";
}
else
{
int mid = path[u][v];
printfPath(path, u, mid);
printfPath(path, mid, v);
}
}
void Floyd(MGraph g, int dist[][maxSize], int path[][maxSize]){
for(int i = 1; i <= g.n; i++)
for(int j = 1; j <= g.n; j++){
dist[i][j] = g.edges[i][j];
path[i][j] = -1;
}
for(int i = 1; i <= g.n; i++)
for(int j = 1; j <= g.n; j++)
for(int k = 1; k <= g.n; k++){
if(dist[i][j] > dist[i][k] + dist[k][j]){
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = k;
}
}
cout << "请输入你要找的两个城市:" << endl;
int u, v;
cin >> u >> v;
if(dist[u][v] == INF)
{
cout << u << " 到 " << v << " 没有通路 " << endl;
}
cout << "路径为:" << u << " ";
printfPath(path, u, v);
cout << "路径长度为:" << dist[u][v] << endl;
}
int main()
{
MGraph adjacent; //邻接矩阵
AGraph adjacency; //临街表
int x, y; //x村y村
double z; //x村y村 距离为z
Road road[maxSize];
//以下为邻接矩阵存图
cout << "请输入几个村庄,几条边(无向图,村庄数从1开始编号):" << endl;
cin >> n >> e;
adjacent.e = e;
adjacent.n = n;
for(int i = 1; i <= n; i++)
{
adjacent.vex[i] = i;
}
//以下为邻接表存图
adjacency.e = e;
adjacency.n = n;
for(int i = 1; i <= n; i++)
{
adjacency.adjlist[i].data = i;
adjacency.adjlist[i].firstarc = NULL;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
if(i == j)
adjacent.edges[i][j] = 0;
else
adjacent.edges[i][j] = INF;
}
cout << "请输入村庄和村庄,村庄之间的路径:" << endl;
for(int i = 1; i <= e; i++)
{
cin >> x >> y >> z;
road[i].a = x;
road[i].b = y;
road[i].distance = z;
//以下为邻接矩阵存图
if(adjacent.edges[x][y] > z)
{
adjacent.edges[x][y] = z;
adjacent.edges[y][x] = z;
}
//以下为邻接表存图
ArcNode *p = new ArcNode;
p->adjvex = y;
p->nextarc = adjacency.adjlist[x].firstarc;
p->info = z;
adjacency.adjlist[x].firstarc = p;
p = new ArcNode;
p->adjvex = x;
p->nextarc = adjacency.adjlist[y].firstarc;
p->info = z;
adjacency.adjlist[y].firstarc = p;
}
cout << "邻接矩阵DFS :" << endl;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(vis[i] == 0)
DFSMGraph(adjacent, i);
cout << endl;
cout << "邻接表DFS :" << endl;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(vis[i] == 0)
DFSAGraph(adjacency, i);
cout << endl;
cout << "邻接矩阵BFS :" << endl;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
if(vis[i] == 0)
BFSMGraph(adjacent, i);
cout << endl;
cout << "邻接表BFS :" << endl;
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; i++)
{
if(vis[i] == 0)
BFSAGraph(adjacency, i);
}
cout << endl;
if(GisTree(adjacent))
cout << "这个图是树" << endl;
else
cout << "这个图不是树" << endl;
sort(road+1,road+n+1,cmp);
for(int i = 1 ;i <= n ;i++)
{
f[i] = i;
distances[i] = INF;
}
int sum = 0;
int count = 0;
if(e < n-1)
{
cout << "无法用kruskal,生成最小生成树,因为边太少" << endl;
}
else
{
Kruskal(distances, road);
for(int i = 1; i <= n ; i++)
{
if( f[i] == i)
count ++;
}
if(count == 1)
{
for(int i = 1; i <= distances[0]; i++)
sum += distances[i];
cout << "Kruskal算法最小生成树的值为 = " << sum << endl;
}
else
{
cout << "无法用kruskal,生成最小生成树,因为不是连通图" << endl;
}
}
sum = 0;
count = 0;
lowcost = new int[n + 1];
vset = new int[n + 1];
if(e < n-1)
{
cout << "无法用Prim,生成最小生成树,因为边太少" << endl;
}
else
{
Prim(adjacent,lowcost, vset, 1);
for(int i = 1; i <= n ; i++)
{
if(lowcost[i] == INF)
count++;
}
if(!count)
{
for(int i = 1; i <= lowcost[0]; i++)
sum += lowcost[i];
cout << "Prime算法最小生成树的值为 = " << sum << endl;
}
else
{
cout << "无法用Prim,生成最小生成树,因为不是连通图" << endl;
}
}
memset(vis, 0, sizeof(vis));
int v;
cout << "请输入你想要找单元最短路径的顶点:" << endl;
cin >> v;
if( v > adjacent.n )
{
cout << "没有这么多村庄,村庄数目为: " << adjacent.n << " 请重新输入:"<< endl;
cin >> v;
}
if( v == 0 )
{
cout << "村庄编号从1开始,村庄数目为: " << adjacent.n << " 请重新输入:"<< endl;
cin >> v;
}
Dijkstra(adjacent, v, distances, path); // 邻接矩阵
//AGDijkstra(adjacency, v, distances, path); //邻接表
Floyd(adjacent, distant, fpath);
return 0;
}