在下列图的应用中选做三项:
⑴求无向连通网的最小生成树;
⑵对有向图进行拓扑排序;
⑶求AOE网的关键路径;
⑷求单源点出发的最短路径。
/*
prim
6
a 3 1 6 2 1 3 5
b 3 0 6 2 5 4 3
c 5 0 1 1 5 3 5 4 6 5 4
d 3 0 5 2 5 5 2
e 3 1 3 2 6 5 6
f 3 2 4 3 2 4 6
topo
8
a 2 2 1 3 1
b 1 4 1
c 1 5 1
d 1 6 1
e 1 6 1
f 1 7 1
g 1 7 1
h 0
Dijkstra
6
a 3 5 100 4 30 2 10
b 1 2 5
c 1 3 50
d 1 5 10
e 2 3 20 5 60
f 0
0
*/
#include<bits/stdc++.h>
#include<stack>
#define Maxv 66
//vertex顶点 arc 弧 Adjacency list邻接表
typedef char ElemType;
int visit[Maxv]; //节点是否访问过
using namespace std;
int visitcnt=0;//已经访问的个数
typedef struct nodea{
int head;
int tail;
int weight;
struct nodea *next;
}ANode,*ANodep; //弧
typedef struct{
ElemType data;
ANode *firstarc;
}VNode; //顶点
typedef struct nodev{
VNode vexs[Maxv];
int vexnum;
int arcnum;
}ALGraph;
void CreateGraph(ALGraph &graph){
graph.vexnum=0;
graph.arcnum=0;
cout<<"创建图模块"<<endl;
cout<<"请输入图的结点个数t,再输入t行数据(数据 出度 (位置#权重))"<<endl;
int t;
cin>>t;//结点个数
graph.vexnum=t;
for(int i=0;i<t;i++){
char d;
int n;
cin>>d>>n; //数据,出度
graph.arcnum+=n;
graph.vexs[i].data=d;
ANodep newarc,head,lastp;
head=(ANodep)malloc(sizeof(ANode));//带头节点
head->next=NULL;
if(!head) exit (-1);
graph.vexs[i].firstarc=head;
lastp=head;
while(n--){
int out,weight1;
cin>>out>>weight1;
ANodep newarc=(ANodep)malloc(sizeof(ANode));
if(!newarc) exit(-1);
newarc->head=i;
lastp->next=newarc;
newarc->next=NULL;
newarc->head=out;
newarc->weight=weight1; //默认权重都是1
lastp=lastp->next;
}
}
graph.arcnum/=2;
}
void output(ALGraph graph){
cout<<"\n输出邻接表"<<endl;
for(int i=0;i<graph.vexnum;i++)
{
cout<<graph.vexs[i].data<<' ';
ANodep nowp=graph.vexs[i].firstarc->next;
while(nowp!=NULL){
cout<<' '<<nowp->head<<'#'<<nowp->weight;
nowp=nowp->next;
}
cout<<endl;
}
cout<<endl;
}
void prim(ALGraph graph){
cout<<"最小生成树";
int dis[Maxv];//记录i点距离已选所有点中的最小距离
int link[Maxv] ;//记录 i点最小距离是和 link【i】关联的
ALGraph newgraph;
newgraph.arcnum=0;
newgraph.vexnum=graph.vexnum;
for(int i=0;i<graph.vexnum;i++){
newgraph.vexs[i].data=graph.vexs[i].data;
ANodep newarc=(ANodep)malloc(sizeof(ANode));
newgraph.vexs[i].firstarc=newarc;
newarc->next=NULL;
}
memset(link,0,sizeof(link));
memset(dis,0x3f,sizeof(dis));
//0号顶点已经到位
dis[0]=0;
int vexcnt=1;
int newv=0;//刚选中的顶点下标
while(vexcnt<graph.vexnum){
ANodep nowarc=graph.vexs[newv].firstarc->next;
while(nowarc){
int vexid=nowarc->head;
if(nowarc->weight<dis[vexid]){
link[nowarc->head]=newv;
dis[vexid]=nowarc->weight;
}
nowarc=nowarc->next;
}
int min=0x3f3f3f3f,minid;
for(int i=0;i<graph.vexnum;i++){
if(dis[i]<min && dis[i]!=0 ){
min=dis[i];
minid=i;
}
}
//找到了需要加入的点的下标minid,另一个是link[mindid]
ANodep linkp1=newgraph.vexs[minid].firstarc;
ANodep linkp2=newgraph.vexs[link[minid]].firstarc;
newgraph.arcnum+=2;
ANodep newarc1,newarc2;
while(linkp1->next) linkp1=linkp1->next;
while(linkp2->next) linkp2=linkp2->next;
//找到了要插入的位置
newarc1=(ANodep)malloc(sizeof(ANode));
newarc2=(ANodep)malloc(sizeof(ANode));
newarc1->next=NULL;
newarc2->next=NULL;
newarc1->head=link[minid];
newarc1->weight=dis[minid];
newarc2->head=minid;
newarc2->weight=dis[minid];
dis[minid]=0;
linkp1->next=newarc1;
linkp2->next=newarc2;
vexcnt++;
newv=minid;
}
output(newgraph);
}
void topo(ALGraph graph){
cout<<"拓扑排序"<<endl;
int numarc[Maxv];//记录某个点的入度
memset(numarc,0,sizeof(numarc));
for(int i=0;i<graph.vexnum;i++){
ANodep newarc;
newarc=graph.vexs[i].firstarc->next;
while(newarc){
numarc[newarc->head]++;
newarc=newarc->next;
}
}
int cnt=0;
while(cnt<graph.vexnum){
int k;
for(k=0;k<graph.vexnum;k++){
if(numarc[k]==0) break;
}
numarc[k]=0x3f3f3f3f;
//找到入度为0的点k
cout<<graph.vexs[k].data<<' ';
ANodep newarcs;
newarcs=graph.vexs[k].firstarc->next;//用于减少的入度
cnt++;
while(newarcs){
numarc[newarcs->head]--;
newarcs=newarcs->next;
}
}
cout<<endl;
}
void Dijkstra(ALGraph graph){
int path[Maxv];
memset(path,-1,sizeof(path));
cout<<"最短路径"<<endl;
cout<<"请输入起点下标" <<endl;
int start;
cin>>start;
int initial=start;
bool collected[Maxv];
int dis[Maxv];
memset(dis,0x3f,sizeof(dis));
memset(collected,0,sizeof(collected));
//全都没有选中;
collected[start]=1;
//选中起点;
dis[start]=0;
int cnt=1,j;
while(cnt<graph.vexnum){
ANodep newarc=graph.vexs[start].firstarc->next;
while(newarc){
if(dis[newarc->head]>dis[start]+newarc->weight){
dis[newarc->head]=dis[start]+newarc->weight;
path[newarc->head]=start;
}
newarc=newarc->next;
}
int min=0x3f3f3f3f+1,minid;
for(j=0;j<graph.vexnum;j++){//j是寻找的点的下标
if(dis[j]<min && collected[j]==0){
min=dis[j];
minid=j;
}
}//此时要加入的点时 minid,值为min
collected[minid]=1;
start=minid;
cnt++;
}
//输出
for(int i=0;i<graph.vexnum;i++){
stack<int> st;
if(dis[i]>=0x3f3f3f3f)
cout<<"起点 "<<graph.vexs[initial].data<<" 到点 "<<graph.vexs[i].data<<" 不连通"<<endl;
else
{
cout<<"起点 "<<graph.vexs[initial].data<<" 到点 "<<graph.vexs[i].data<<" 的最短距离是 "<<dis[i]<<endl;
st.push(i);
int k=i;
while(path[k]!=-1){
st.push(path[k]);
k=path[k];
}
cout<<" 路径是";
while(!st.empty()){
int pathi=st.top();
cout<<" "<<graph.vexs[pathi].data;
st.pop();
}
cout<<endl;
}
}
}
int main()
{
ALGraph graph;
CreateGraph(graph);
prim(graph);
CreateGraph(graph);
topo(graph);
CreateGraph(graph);
Dijkstra(graph);
return 0;
}