Data_Structure/作業/unit12/DS7_matrix.cpp
2025-01-20 21:30:53 +08:00

180 lines
4.1 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_V 100 /*最大節點數*/
#define Infinite 1073741823
long int dist[MAX_V+1][MAX_V+1];
int path[MAX_V+1][MAX_V+1]; // 追蹤路徑的矩陣
int N; // 節點數量
int source, sink; // 起點和終點
void init();
bool floydWarshall();
void output_path();
void output_step();
void print_path(int start, int end);
int main() {
init();
// 檢查是否存在負權迴路
if (floydWarshall()) {
printf("\n警告:圖形中存在負權迴路,計算結果可能不正確!\n");
output_path();
} else {
output_path();
}
return 0;
}
void init() {
FILE *fptr;
int i, j, weight, line_count = 0;
char line[256];
fptr = fopen("shortestPath_matrix.dat", "r");
if (fptr == NULL) {
perror("shortestPath_matrix.dat");
exit(1);
}
// 計算總頂點數
while (fgets(line, sizeof(line), fptr)) {
line_count++;
}
N = line_count;
rewind(fptr);
// 初始化距離矩陣與路徑矩陣
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
if (i == j) {
dist[i][j] = 0;
path[i][j] = i;
} else {
dist[i][j] = Infinite;
path[i][j] = -1;
}
}
}
// 讀取完整矩陣
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
if (fscanf(fptr, "%d", &weight) == 1) {
if (weight != 0 && i != j) { // 只處理非零且非對角線的權重
dist[i][j] = weight;
path[i][j] = i;
}
}
}
}
fclose(fptr);
printf("檔案內權重如下\n");
output_step();
printf("\n輸入起始節點 (1~%d): ", N);
scanf("%d", &source);
printf("輸入目標節點 (1~%d): ", N);
scanf("%d", &sink);
}
bool floydWarshall(){
int k, i, j;
bool has_negative_cycle = false;
long int temp_dist[MAX_V+1][MAX_V+1];
// 主要的 Floyd-Warshall 演算法
for (k = 1; k <= N; k++) {
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
if (dist[i][k] != Infinite &&
dist[k][j] != Infinite &&
dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
path[i][j] = path[k][j];
}
}
}
}
// 複製目前的距離矩陣
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
temp_dist[i][j] = dist[i][j];
}
}
// 再執行一次迭代來檢查負權迴路
for (k = 1; k <= N; k++) {
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
if (dist[i][k] != Infinite &&
dist[k][j] != Infinite &&
dist[i][k] + dist[k][j] < temp_dist[i][j]) {
has_negative_cycle = true;
goto end_check; // 找到負權迴路後直接跳出
}
}
}
}
end_check:
return has_negative_cycle;
}
void print_path(int start, int end) {
if (start == end) {
printf("頂點%d", start);
return;
}
if (path[start][end] == -1) {
printf("無路徑");
return;
}
print_path(start, path[start][end]);
printf(" → %d", end);
}
void output_step(){
int i, j;
printf("\t");
for (j = 1; j <= N; j++) {
printf("V%d\t", j);
}
printf("\n");
for (i = 1; i <= N; i++) {
printf("V%d\t", i);
for (j = 1; j <= N; j++) {
if (dist[i][j] == Infinite)
printf("\t");
else
printf("%2ld\t", dist[i][j]);
}
printf("\n");
}
}
void output_path(){
int i, j;
printf("\n節點間最短距離矩陣:\n");
output_step();
if (dist[source][sink] == Infinite) {
printf("\n節點 V%d 到節點 V%d 沒有路徑\n", source, sink);
} else {
printf("\n從節點 V%d 到節點 V%d 的最短距離為:%ld\n",
source, sink, dist[source][sink]);
printf("最短路徑:");
print_path(source, sink);
printf("\n");
}
}