最小生成树、拓扑排序和最短路径
实验内容:
(1)键盘输入数据,分别建立一个有向图的邻接表和一个无向图的邻接矩阵。
(2)输出该邻接表和邻接矩阵。
(3)以有向图的邻接表为基础输出它的拓扑排序序列。
(4)以无向图的邻接矩阵为基础实现最小生成树的PRIM算法。
(5)以无向图的邻接矩阵为基础实现Dijkstra算法输出单源点到其它顶点的最短路径。
(6)在主函数中设计一个简单的菜单,分别调试上述算法。
代码:
#include<bits/stdc++.h>
#define N 1009
using namespace std;
const int INF = 0x3f3f3f3f;
vector<int> mp1[N];
int mp2[N][N], vis[N], n, nn, IN[N];
void menu()
{
printf("\t1.建图\n");
printf("\t2.输出图\n");
printf("\t3.拓扑排序\n");
printf("\t4.Prim\n");
printf("\t5.dij\n");
printf("\t6.退出\n");
}
void create_GV()
{
printf("\ta.无向图\n");
int m, u, v, w;
scanf("%d%d", &nn, &m);
memset(mp2, 0x3f, sizeof(mp2));
//for(int i = 1; i <= nn; i++) mp2[i][i] = 0;
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &w);
mp2[u][v] = mp2[v][u] = min(mp2[u][v], w);
}
printf("\tb.有向图\n");
scanf("%d%d", &n, &m);
memset(IN, 0, sizeof(IN));
for(int i = 0; i <= n; i++) mp1[i].clear();
for(int i = 1; i <= m; i++)
{
scanf("%d%d", &u, &v);
mp1[u].push_back(v);
IN[v]++;
}
}
void display()
{
printf("\ta.无向图\n");
for(int i = 1; i <= nn; i++)
{
for(int j = i+1; j <= nn; j++)
{
if(mp2[i][j] == INF) continue;
printf("%d %d %d\n", i, j, mp2[i][j]);
}
}
printf("\tb.有向图\n");
for(int i = 1; i <= n; i++)
{
int k = mp1[i].size();
for(int j = 0; j < k; j++)
{
printf("%d %d\n", i, mp1[i][j]);
}
}
}
void toposort()
{
int cnt = 0;
char ans[N];
stack<int> s;
for(int i = 1; i <= n; i++)
{
if(!IN[i]) s.push(i);
}
if(s.empty())
{
printf("Error!\n");
return ;
}
while(!s.empty())
{
if(s.size() > 1)
{
printf("Error!\n");
return ;
}
int u = s.top(); s.pop();
ans[cnt++] = u + '0'; ans[cnt++] = ' ';
int k = mp1[u].size();
for(int j = 0; j < k; j++)
{
int v = mp1[u][j];
IN[v]--;
if(!IN[v]) s.push(v);
}
}
ans[cnt] = '\0';
puts(ans);
}
int Prim()
{
int d[N];
for(int i = 1; i <= nn; i++) d[i] = mp2[1][i];
memset(vis, 0, sizeof(vis));
d[1] = 0;
int ans = 0;
for(int i = 1; i <= nn; i++)
{
int v = -1;
for(int j = 1; j <= nn; j++) if(!vis[j] && (v == -1 || d[j] < d[v])) v = j;
if(v == -1) break;
vis[v] = 1;
ans += d[v];
for(int j = 1; j <= nn; j++)
{
if(!vis[j] && d[j] > mp2[v][j]) d[j] = mp2[v][j];
}
}
for(int i = 1; i <= nn; i++) if(d[i] == INF) return -1;
return ans;
}
int dij(int s, int e)
{
int d[N];
for(int i = 1; i <= nn; i++) d[i] = mp2[s][i];
memset(vis, 0, sizeof(vis));
d[s] = 0;
for(int i = 1; i <= nn; i++)
{
int v = -1;
for(int j = 1; j <= nn; j++) if(!vis[j] && (v == -1 || d[j] < d[v])) v = j;
if(v == -1) break;
vis[v] = 1;
for(int j = 1; j <= nn; j++)
{
if(!vis[j] && d[j] > d[v] + mp2[v][j]) d[j] = d[v] + mp2[v][j];
}
}
return d[e] == INF ? -1 : d[e];
}
/*
样例1:
5 7
1 2 3
1 3 2
2 3 1
2 4 2
2 5 1
3 5 100
4 5 3
3 3
1 2
2 3
3 1
***********************************
样例2:
5 7
1 2 3
1 3 2
2 3 1
2 4 2
2 5 1
3 5 100
4 5 3
6 9
1 2
1 3
2 3
2 4
3 4
3 6
4 5
4 6
6 5
*/
int main()
{
while(true)
{
int sel;
menu();
scanf("%d", &sel);
switch(sel)
{
case 1: create_GV(); break;
case 2: display(); break;
case 3: toposort(); break;
case 4: printf("%d\n", Prim()); break;
case 5:
{
int s, e;
scanf("%d%d", &s, &e);
printf("%d\n", dij(s, e));
} break;
}
if(sel == 6) break;
}
return 0;
}