1. 给定一个图G, 判断是否存在一条从 S 到 T 的长为 K 的路径。
[Accepted 2013/03/27]
1) 邻接矩阵版
//File name : is_path.hpp
#ifndef _IS_PATH_H_
#define _IS_PATH_H_
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 100
struct graph {
int nodes_num;
int G[MAX_NUM][MAX_NUM];
};
void init_graph(struct graph* gra);
bool find_path(struct graph* gra, int S, int T, int K);
bool is_empty(struct graph* gra);
int read_graph(char* file_name, struct graph* gra, int* S, int* T, int* K);
bool adjacent(struct graph* gra, int S, int T);
#endif
//File name : is_path.cpp
#include "is_path.h"
void init_graph(struct graph* gra) {
//初始化图
int i = 0;
int j = 0;
gra->nodes_num = 0;
for(i = 0; i < MAX_NUM; i++)
for(j = 0; j < MAX_NUM; j++)
(gra->G)[i][j] = 0;
}
bool is_empty(struct graph* gra) {
//判空
if(gra->nodes_num == 0) return true;
else return false;
}
bool adjacent(struct graph* gra, int S, int T) {
if((gra->G)[S][T] == 1) return true;
else return false;
}
bool find_path(struct graph* gra, int S, int T, int K) {
//在图G中,是否存在一条从S到T的长为K的路径
int i = 0;
if(!is_empty(gra) && K > 0) {
if(K == 1) return adjacent(gra, S, T);
for(i = 0; i < gra->nodes_num; i++) {
if(adjacent(gra, S, i))
if(find_path(gra, i, T, K - 1))
return true;
}
return false;
}
}
int read_graph(char* file_name, struct graph* gra, int* S, int* T, int* K) {
FILE* fp = NULL;
int i = 0;
int j = 0;
if((fp = fopen(file_name, "r")) == NULL) {
printf("Can not open the file!");
exit(-1);
}
fscanf(fp, "%d", &(gra->nodes_num));
fscanf(fp, "%d", S);
fscanf(fp, "%d", T);
fscanf(fp, "%d", K);
while(!feof(fp)) {
fscanf(fp, "%d", &i);
fscanf(fp, "%d", &j);
(gra->G)[i][j] = 1;
}
fclose(fp);
return 0;
}
int main() {
int S = 0;
int T = 0;
int K = 0;
char file_name[50] = "data.txt";
struct graph* gra = NULL;
gra = (struct graph*) malloc(sizeof(struct graph));
if(gra == NULL) {
printf("Allocation fails!");
exit(-1);
}
init_graph(gra);
read_graph(file_name, gra, &S, &T, &K);
if(S < 0 || S >= gra->nodes_num || T < 0 || T >= gra->nodes_num) {
printf("Node S or T does not exist!");
}
else {
if(find_path(gra, S, T, K)) printf("The path from S to T exists!");
else printf("The path from S to T does not exist!");
}
return 0;
}
2)邻接链表版
[Accepted 2013/03/28]
// File name: is_path2.h
#ifndef _IS_PATH_H_
#define _IS_PATH_H_
#include <stdio.h>
#include <stdlib.h>
struct node_v {
int info;
struct node_v* next;
struct node_e* edge;
};
struct node_e {
int info;
struct node_e* next;
struct node_v* vertex;
};
bool find_path(struct node_v * graph, int S, int T, int K, int v_num);
struct node_v* read_graph(char* file_name, struct node_v * graph, int* S, int* T, int* K, int* v_num);
bool adjacent(struct node_v* graph, int S, int T);
struct node_v* make_vertex(int i);
struct node_e* make_edge(int i);
struct node_v* joint(struct node_v* graph, int S, int T);
#endif
// File name: is_path2.cpp
#include "is_path2.h"
struct node_v* make_vertex(int i) {
//新建顶点节点
struct node_v* p = NULL;
p = (struct node_v*) malloc(sizeof(struct node_v));
if(p == NULL) {
printf("Allocation fails!");
exit(-1);
}
p->edge = NULL;
p->next = NULL;
p->info = i;
return p;
}
struct node_e* make_edge(int i) {
//新建边的节点
struct node_e* p = NULL;
p = (struct node_e*) malloc(sizeof(struct node_e));
if(p == NULL) {
printf("Allocation fails!");
exit(-1);
}
p->vertex = NULL;
p->next = NULL;
p->info = i;
return p;
}
struct node_v* joint(struct node_v* graph, int S, int T) {
//构造一条由S到T的边
int flag = 0;
struct node_v* p = graph;
struct node_e* q = NULL;
struct node_e* q_pre = NULL;
while(p != NULL) { //找到S节点
if(p->info == S) {
flag = 1;
break;
}
p = p->next;
}
if(flag == 0) {
printf("Node \"%s\" does not exist!", S);
exit(-1);
}
flag = 0;
q_pre = q = p->edge;
while(q != NULL) { //找到S节点的边的末尾
q_pre = q;
q = q->next;
}
q = make_edge(T);
if(q_pre == NULL) p->edge = q;
else q_pre->next = q;
p = graph;
while(p != NULL) { //找到T节点
if(p->info == T) {
flag = 1;
break;
}
p = p->next;
}
if(flag == 0) {
printf("Node \"%s\" does not exist!", T);
exit(-1);
}
q->vertex = p;
return graph;
}
bool adjacent(struct node_v* graph, int S, int T) { //判断S和T是否相邻
int flag = 0;
struct node_v* p = graph;
struct node_e* q = NULL;
while(p != NULL) { //找到S节点
if(p->info == S) {
flag = 1;
break;
}
p = p->next;
}
if(flag == 0) { //没有找到S节点
printf("Node \"%d\" does not exist!", S);
exit(-1);
}
flag = 0;
q = p->edge;
while(q != NULL) { //看S节点的边里是否存在T
if(q->info == T) {
flag = 1;
return true;
}
q = q->next;
}
if(flag == 0) return false; //没有找到T节点
}
bool find_path(struct node_v* graph, int S, int T, int K, int v_num) {
//在图G中,是否存在一条从S到T的长为K的路径
int i = 0;
struct node_v* p = graph;
struct node_e* q = NULL;
if(graph == NULL) {
printf("The graph is empty!");
exit(-1);
}
if(S < 0 || S >= v_num ) {
printf("Node \"%d\" does not exist!", S);
exit(-1);
}
if(T < 0 || T >= v_num) {
printf("Node \"%d\" does not exist!", T);
exit(-1);
}
if(K < 1) {
printf("The value of K must be more than 0!");
exit(-1);
}
if(K == 1) return adjacent(graph, S, T);
while(p != NULL) {
if(adjacent(graph, S, p->info))
if(find_path(graph, p->info, T, K - 1, v_num))
return true;
p = p->next;
}
return false;
}
struct node_v* read_graph(char* file_name, struct node_v* graph, int* S, int* T, int* K, int* v_num) { //读取数据
FILE* fp = NULL;
int i = 0;
int j = 0;
struct node_v* p = NULL;
if((fp = fopen(file_name, "r")) == NULL) {
printf("Can not open the file!");
exit(-1);
}
fscanf(fp, "%d", v_num); //读取顶点总数 建立顶点链
for(i = (*v_num) - 1; i >= 0 ; i--) {
p = make_vertex(i);
p->next = graph;
graph = p;
}
fscanf(fp, "%d", S);
fscanf(fp, "%d", T);
fscanf(fp, "%d", K);
while(!feof(fp)) { //建立边的链
fscanf(fp, "%d", &i);
fscanf(fp, "%d", &j);
graph = joint(graph, i, j);
}
fclose(fp);
return graph;
}
int main() {
int S = 0;
int T = 0;
int K = 0;
int v_num = 0;
char file_name[50] = "data.txt";
struct node_v* graph = NULL;
graph = read_graph(file_name, graph, &S, &T, &K, &v_num);
if(find_path(graph, S, T, K, v_num)) printf("The %d-path from \"%d\" to \"%d\" exists!", K, S, T);
else printf("The %d-path from \"%d\" to \"%d\" does not exist!", K, S, T) ;;
return 0;
}
2. 给定一个图G, 求解该图相关的转移闭包(path 矩阵)。
[Accepted 2013/03/29]
int multiple(int pro[][MAX_NUM], int mul1[][MAX_NUM], int mul2[][MAX_NUM], int N) {
//N*N矩阵乘法
int i = 0;
int j = 0;
int k = 0;
for(i = 0; i < N; i++)
for(j = 0; j < N; j++) {
for(k = 0; k < N; k++)
pro[i][j] = (int) (pro[i][j] || (mul1[i][k] && mul2[k][j]));
//if(pro[i][j] > 1) pro[i][j] = 1;
}
return 0;
}
int path_matrix(struct graph* gra, int path[][MAX_NUM], int K) {
//求path矩阵
int i = 0;
int j = 0;
int temp[MAX_NUM][MAX_NUM] = {0};
int zero[MAX_NUM][MAX_NUM] = {0};
int pathk[MAX_NUM][MAX_NUM] ={0};
for(i = 0; i < gra->nodes_num; i++)
for(j = 0; j < gra->nodes_num; j++) {
path[i][j] = gra->G[i][j];
temp[i][j] = gra->G[i][j];
pathk[i][j] = gra->G[i][j];
}
if(!is_empty(gra) && K > 0) {
for(i = 1; i < K; i++) {
if(i == 0) copy(gra->G, path, gra->nodes_num);
else {
multiple(pathk, path, temp, gra->nodes_num);
for(i = 0; i < gra->nodes_num; i++)
for(j = 0; j < gra->nodes_num; j++) {
path[i][j] = (int)(path[i][j] || pathk[i][j]);
}
}
}
}
return 0;
}
建议先采用邻接矩阵的表示形式做,如有空余时间,则再练一练邻接链表的表示形式。