图的操作:
1.图的存储结构使用邻接矩阵。
2.创建图操作类,支持BFS遍历、DFS遍历、求单源最短路径、求最小生成树、判断是否存在回路等五个功能,这些功能封装成图操作类的成员函数
3. 采用“起始节点,终止节点,权值”输入图的m条边,创建图。
4. 输出从节点1开始的BFS遍历、DFS遍历节点遍历顺序。
5. 输出从节点1到其余节点的最短路径及最短路径长度,如果没有路径,输出0。
6. 输出图的最小生成树包含的边,边用“起始节点,终止节点,权值”表示。
输入输出说明:
输入:
第1行输入2个整数,图的节点数n(不超过10个)、边数m。
接下来m行,每行3个整数。采用“起始节点,终止节点,权值”输入图的m条边。
输出:
第1行为图的BFS遍历
第2行为图的DFS遍历
接下来n-1行,为图中第1个节点到其他节点的最短路径,如果没有路径,路径长度输出“0”。格式为:最短路径 路径长度。
接下来输出图的最小生成树包含的边,边用“起始节点,终止节点,权值”表示,按权值从小到大输出最小生成树的边。
最后一行输出大写字母 YES 或 NO:YES代表图中有环,NO代表图中无环。
输入:
6 9
1 2 10
1 4 20
1 6 2
2 3 3
2 4 5
3 5 15
4 5 11
4 6 10
5 6 3
输出:
1 2 4 6 3 5
1 2 3 5 4 6
1 2 10
1 2 3 13
1 6 4 12
1 6 5 5
1 6 2
1 6 2
2 3 3
5 6 3
2 4 5
1 2 10
YES
#include
#include
#include
#define INFINITY 99999
#define UNVISITED 0
#define VISITED 1
#define Max 10
using namespace std;
template<class E>
class Queue {
//队列ADT
private:
void operator = (const Queue&) {
}
Queue(const Queue&) {
}
int maxsize;
int front;
int rear;
E* listArray;
public:
Queue(int size = 99) {
//构造函数
maxsize = size;
rear = 0;
front = 1;
listArray = new E[size];
}
~Queue() {
delete[] listArray;
}
//析构函数
void clear() {
//清空
rear = 0;
front = 1;
}
int length() {
//返回队列长度
return ((rear + maxsize) - front + 1) % maxsize;
}
void enqueue(const E& it) {
//入队
if (((rear + 2) % maxsize) != front) {
rear = (rear + 1) % maxsize;
listArray[rear] = it;
}
}
E dequeue() {
//出队
if (length() != 0) {
E it = listArray[front];
front = (front + 1) % maxsize;
return it;
}
}
const E& frontValue() {
//获取队尾值
if (this.length() != 0)
return listArray[front]; else
exit(0);
}
};
class Graphm {
//图类
private:
int numVertex;//顶点数
int numEdge;//边数
int (**matrix);//邻接矩阵
int *mark;//记录
public:
Graphm(int n) {
//图的构造函数
numVertex = n;
numEdge=0;
matrix =(int **) new int*[n];//初始化图
for (int i=0;i<n;i++)
matrix[i]=new int[n];
for (int i=0;i<n;i++)
for (int j=0;j<n;j++)
matrix[i][j]=0;
mark= new int[n];
}
~Graphm() {
//析构图
for (int i=0;i<numVertex;i++)
delete []matrix[i];
delete []matrix;
delete []mark;
}
public:
void setMark(int v, int val) {
//标记
mark[v]=val;
}
int getMark(int v) {
//获取标记
return mark[v];
}
void setEdge(int v1, int v2, int weight) {
//加边
if (matrix[v1][v2]==0) numEdge++;
matrix[v1][v2] = matrix[v2][v1] = weight;
}
void delEdge(int v1, int v2) {
//删除边
matrix[v1][v2] = matrix[v2][v1]=0;
}
int weight(int v1, int v2) {
//获取边上的权值
return matrix[v1][v2];
}
bool isEdge(int v1, int v2) {
//判断是否有边
if (matrix[v1][v2]!=0) return true;
return false;
}
int n() {
//获取顶点数
return numVertex;
}
int e() {
//获取边数
return numEdge;
}
int first(int v) {
//获取顶点的第一个邻接点
for (int i=0;i<numVertex;i++) {
if (matrix[v][i]!=0)
return i;
}
return numVertex;
}
int next(int v, int w) {
//获取顶点的下一个邻接点
for (int i=w+1;i<numVertex;i++) {
if (matrix[v][i]!=0)
return i;
}
return numVertex;
}
};
class OpertaionG{
//图操作类
private:
Graphm *G;//图
Graphm *MST;
int cnt;
struct e {
int s;
int e;
int w;
}
;
int *father;
public:
OpertaionG(Graphm *g){
G = g;
}
void DFS() {
//深度优先遍历
for (int i=0;i<G->n();i++)
G->setMark(i,UNVISITED);
for (int i=0;i<G->n();i++)
if (G->getMark(i)== UNVISITED)
helpDfs(i,0);
}
void BFS() {
//广度优先遍历
cnt=0;
Queue<int>* q= new Queue<int>;
for (int i=0;i<G->n();i++)
G->setMark(i,UNVISITED);
for (int i=0;i<G->n();i++)
if(G->getMark(i)==UNVISITED)
helpBfs(i,q);
delete q;
}
void Dijkstra(int start) {
//单元最短路径
int n = G->n();
for (int i=0;i<n;i++)
G->setMark(i,UNVISITED);
int D[n];//最短路径距离
int pre[n];//存储最短路径
memset(pre,-1,sizeof (pre));
for (int i=0;i<n;i++)
D[i]=INFINITY;
D[start]=0;
for (int i=0;i<n;i++) {
int v = minVertex(D);
if (v==-1) return;
G->setMark(v,VISITED);
for (int i=G->first(v);i<n;i=G->next(v,i)) {
if (G->getMark(i)==UNVISITED && D[i]>D[v]+G->weight(v,i)) {
D[i]=D[v]+G->weight(v,i);
pre[i]=v;
}
}
}
for (int i=1;i<n;i++) {
if(D[i]==INFINITY) cout<<0+1<<" "<<i+1<<0<<endl; else {
cout << 0+1<<" ";
string s="";
int x = i;
while (pre[x]!=-1) {
s=std::to_string(x+1)+" "+s;
//输出+1
x = pre[x];
}
cout<<s<<D[i]<<endl;
}
}
}
void Prim() {
//获取最小生成树
int n = G->n();
for (int i=0;i<n;i++)
G->setMark(i,UNVISITED);
int D[n];
for (int i=0;i<n;i++)
D[i]=INFINITY;
D[0]=0;
struct e E[n];
E[0].s=0;
E[0].e=0;
E[0].w=INFINITY;
for (int i=0;i<n;i++) {
int min = minVertex(D);
if (min==-1) return;
G->setMark(min,VISITED);
for (int i=G->first(min);i<n;i=G->next(min,i))
if (G->getMark(i)==UNVISITED&& D[i]>G->weight(min,i)) {
D[i]=G->weight(min,i);
E[i].s=min;
E[i].e=i;
E[i].w=G->weight(min,i);
}
}
sort(E,E+n,cmp);
for (int i=0;i<n-1;i++)
if (E[i].s<E[i].e)
cout<<E[i].s+1<<" "<<E[i].e+1<<" "<<E[i].w<<endl;
else
cout<<E[i].e+1<<" "<<E[i].s+1<<" "<<E[i].w<<endl;
}
void hasCircle() {
//判断图是否有环
int n = G->n();
father = new int[n];
for (int i=0;i<n;i++)
father[i]=-1;
for (int i=0;i<n;i++)
for (int j=i;j<n;j++) {
if (G->weight(i,j)!=0) {
int y1 = find(i);
int y2 = find(j);
if (y1==y2)
cout<<"NO";
}
}
cout<<"YES";
delete[] father;
}
int find(int v) {
if (father[v]==-1) return v;
return father[v]=find(father[v]);
}
bool static cmp(struct e e1,struct e e2) {
return e1.w<e2.w;
}
int minVertex(int *D) {
//获取最小的邻接点
int minCost=INFINITY;
int flag=-1;
for (int i=0;i<G->n();i++) {
if (minCost>D[i] && G->getMark(i)==UNVISITED) {
minCost=D[i];
flag=i;
}
}
return flag;
}
void helpDfs(int v, int cnt) {
//深度优先遍历的主要实现
if(cnt!=G->n()-1) {
cout<<v+1<<" ";
cnt+=1;
} else cout<<v+1<<endl;
G->setMark(v,VISITED);
for (int i = G->first(v); i<G->n();i=G->next(v,i)) {
if (G->getMark(i)==UNVISITED)
helpDfs(i,cnt);
}
}
void helpBfs(int v, Queue<int>* q) {
//广度优先遍历的主要实现
q->enqueue(v);
G->setMark(v,VISITED);
while (q->length() != 0) {
int a = q->dequeue();
if (cnt!=G->n()-1) {
cout<<a+1<<" ";
cnt+=1;
} else cout<<a+1<<endl;
for (int i=G->first(a);i<G->n();i=G->next(a,i))
if (G->getMark(i)==UNVISITED) {
q->enqueue(i);
G->setMark(i,VISITED);
}
}
}
};
int main() {
int n,m;
cin>>n>>m;
Graphm *G = new Graphm(n);
int s,e,w;
for (int i=0;i<m;i++) {
cin>>s>>e>>w;
G->setEdge(s-1,e-1,w);
}
OpertaionG *O = new OpertaionG(G);
//广度优先遍历
O->BFS();
//深度优先遍历
O->DFS();
//最短路径
O->Dijkstra(1-1);
//最小生成树
O->Prim();
//判断是否有环
O->hasCircle();
}