题目7:关键路径寻找
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
FILE *fp;
int dui[MAX];
int nidui[MAX];
typedef struct Edgenode
{
int data;
int path;
struct Edgenode *next;
} Edgenode;
struct Linjienode
{
int rudu;
int Ve;
int Vl;
Edgenode *tounode;
} LJbiaonode, LJbiao[MAX];
int MAXshu(int x, int y)
{
return x > y ? x : y;
}
int MINshu(int x, int y)
{
return x > y ? y : x;
}
void topologicalsort(struct Linjienode *LJbiao, int m) //拓扑排序
{
Edgenode *A;
Edgenode *B;
int C;
int cur;
int flag = 0;
int flag1 = 0;
int front = 0, rear = 0;
for (int i = 0; i < MAX; i++)
{
dui[i] = 0;
}
for (int i = 1; i < m + 1; i++)
{
if (LJbiao[i].rudu == 0)
{
LJbiao[i].Ve = 0;
A = LJbiao[i].tounode->next;
dui[++rear] = i;
while (A != NULL)
{
LJbiao[A->data].Ve = MAXshu(A->path + LJbiao[i].Ve, LJbiao[A->data].Ve);
LJbiao[A->data].rudu--;
A = A->next;
}
break;
}
}
flag1 = 1;
while (front - rear != 0)
{
if (flag1 == 1)
{
cur = dui[++front];
}
else
{
cur = dui[front];
}
if (LJbiao[cur].rudu == 0)
{
for (int j = 1; j < m + 1; j++) //结点从头开始遍历一遍,以寻找出新的入读为0的结点
{
for (int k = 1; k < m + 1; k++) //判断是否队列中已经有过入度为0的相同结点
{
if (j == dui[k])
{
flag = j;
break;
}
}
if (LJbiao[j].rudu == 0 && j != flag)
{
dui[++rear] = LJbiao[j].tounode->data;
}
}
A = LJbiao[++front].tounode->next;
while (A != NULL)
{
LJbiao[A->data].Ve = MAXshu(A->path + LJbiao[front].Ve, LJbiao[A->data].Ve);
LJbiao[A->data].rudu--;
A = A->next;
}
}
flag1 = 0;
}
for (int j = 1; j < m + 1; j++) //结点从头开始遍历一遍,以寻找出新的入读为0的结点
{
for (int k = 1; k < m + 1; k++) //判断是否队列中已经有过入度为0的相同结点
{
if (j == dui[k])
{
flag = j;
break;
}
}
if (LJbiao[j].rudu == 0 && j != flag)
{
dui[++rear] = LJbiao[j].tounode->data;
}
}
for (int i = 1; i < m + 1; i++)
{
B = LJbiao[i].tounode->next;
C = LJbiao[i].Ve;
while (B != NULL)
{
if (B->data == dui[rear])
{
while (B != NULL)
{
LJbiao[dui[rear]].Ve = MAXshu(B->path + C, LJbiao[dui[rear]].Ve);
B = B->next;
}
}
else
{
B = B->next;
}
}
}
}
void nitopologicalsort(struct Linjienode *LJbiao, int m) //逆拓扑排序
{
Edgenode *A;
Edgenode *B;
int front, rear;
for (int i = 1; i < m + 1; i++)
{
LJbiao[i].Vl = LJbiao[m].Ve;
}
for (int j = MAX;; j--)
{
if (dui[j] > 0)
{
front = j;
rear = j;
break;
}
}
while (dui[front] != 0)
{
A = LJbiao[dui[front]].tounode->next;
if (dui[front != 0])
{
for (int i = 1; i < m + 1; i++)
{
B = LJbiao[i].tounode->next;
while (B != NULL)
{
if (B->data == dui[front])
{
LJbiao[i].Vl = MINshu(LJbiao[dui[front]].Vl - B->path, LJbiao[i].Vl);
B = B->next;
}
else
B = B->next;
}
}
front--;
}
}
}
int main(void)
{
fp = fopen("guanjianroad.txt", "w");
int m, n, p, q, r;
Edgenode *s;
Edgenode *cur;
Edgenode *X;
printf("请输入图的结点数:");
scanf("%d", &m);
for (int i = 1; i < m + 1; i++)
{
LJbiao[i].tounode = (Edgenode *)malloc(sizeof(Edgenode));
LJbiao[i].tounode->data = i;
LJbiao[i].rudu = 0;
LJbiao[i].Ve = 0;
LJbiao[i].Vl = 0;
}
int current = 1;
int flag = 0;
printf("请输入含有边的两个节点和他们之间的路径长度对如'1 3 2'(表示1和3结点之间路径长度为2)(输入#表示输入完成):");
while (p != m)
{
scanf("%d%d%d", &p, &q, &r);
if (getchar() == '#') //最后输入#代表结束
{
LJbiao[m].tounode->next = NULL;
break;
}
while (p != current)
{
current++;
flag = 0;
}
if (p == current && flag == 0) //把邻接表头连接上边结点
{
s = (Edgenode *)malloc(sizeof(Edgenode));
LJbiao[p].tounode->next = s;
s->data = q;
LJbiao[q].rudu++;
s->path = r;
s->next = NULL;
flag = 1;
}
else if (p == current && flag == 1) //串联
{
cur = (Edgenode *)malloc(sizeof(Edgenode));
s->next = cur;
s = s->next;
s->data = q;
LJbiao[q].rudu++;
s->path = r;
s->next = NULL;
}
}
topologicalsort(LJbiao, m);
nitopologicalsort(LJbiao, m);
fprintf(fp, "关键路径上的点及其之间的边为:\n");
for (int i = 1; i < m + 1; i++)
{
X = LJbiao[i].tounode->next;
if (LJbiao[i].Ve == LJbiao[i].Vl)
{
while (X != NULL)
{
if (LJbiao[X->data].Ve == LJbiao[X->data].Vl)
{
fprintf(fp, "%d--%d ", LJbiao[i].tounode->data, X->data);
}
X=X->next;
}
}
}
fclose(fp);
}
输入
输出