第五次实习是关于图的操作
但实际实习过程中,还是以解出题目为主要目的。简单记录一下
由于牛客网考试系统答题,不敢截屏,所以用手机将题目描述拍了下来
1.DFS和BFS遍历输出
看到类名为Tu
,我自己都笑了
代码
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
class Tu{
public:
int *point;
int **line;
int n;
public:
Tu(int m){
this->n = m;
point = new int[n];
line = (int **)new int*[n];
for(int i = 0;i < n;i++){
line[i] = new int[n];
}
}
~Tu(){
delete point;
for(int i = 0;i < n;i++){
delete line[i];
}
delete line;
}
void create(){
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cin >> line[i][j];
}
}
for(int i = 0;i < n;i++){
point[i] = i;
}
}
void dfs(int x){
stack<int> s;
int j = x;
int *tag = new int[n];
for(int i =0;i < n;i++){
tag[i] = 0;
}
s.push(x);
tag[x] = 1;
cout << point[j] << " ";
while(true){
for(int i = 0;i < n;i++){
if(line[j][i] == 1 && tag[i] == 0){
tag[i] = 1;
s.push(i);
cout << point[i] << " ";
j = i;
break;
}
if(i==n-1){
if(!s.empty()){
j = s.top();
s.pop();
}
else{
return;
}
}
}
}
}
void bfs(int x){
queue<int> q;
int j;
int *tag = new int[n];
for(int i =0;i < n;i++){
tag[i] = 0;
}
q.push(x);
tag[x] = 1;
while(!q.empty()){
j = q.front();
q.pop();
cout << point[j] << " ";
for(int i = 0;i < n;i++){
if(line[j][i] == 1 && tag[i] == 0){
tag[i] = 1;
q.push(i);
}
}
}
}
};
int main()
{
int n;
cin >> n;
Tu tu(n);
tu.create();
cout << "DFS" << endl;
for(int i = 0;i < n;i++){
tu.dfs(i);
cout << endl;
}
cout << "WFS" << endl;
for(int i = 0;i < n;i++){
tu.bfs(i);
cout << endl;
}
return 0;
}
2.Prim和Kruskal最小生成树
这里注意一下compare
,在这里卡了很久
以及prim
从优先级队列取出对头后,如果不符合得放回去
代码
#include <iostream>
#include <queue>
using namespace std;
struct EdgeNode{
int weight;
int left;
int right;
EdgeNode(int _weight = 0,int _left = 0,int _right = 0){
weight = _weight;
left = _left;
right = _right;
}
};
struct compare{
bool operator()(EdgeNode *n1,EdgeNode *n2){
if(n1->weight == n2->weight){
return n1->left > n2->left;
}
return n1->weight > n2->weight;
}
};
class MinTree{
private:
priority_queue<EdgeNode*,vector<EdgeNode*>,compare> q;
int n;
public:
MinTree(int m){n = m;}
~MinTree(){}
void init(int **a){
while(!q.empty()) q.pop();
for(int i = 0;i < n;i++){
for(int j = i+1;j < n;j++){
if(a[i][j] != 0){
EdgeNode *tmp = new EdgeNode(a[i][j],i,j);
q.push(tmp);
}
}
}
}
void kruskal(){
int *point = new int[n];
for(int i = 0;i < n;i++){
point[i] = i;
}
int **k = (int **) new int*[n];
for(int i = 0;i < n;i++){
k[i] = new int[n];
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
k[i][j] = 0;
}
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cout << k[i][j] << " ";
}
cout << endl;
}
cout << endl;
int count = 0;
EdgeNode *tmp = new EdgeNode();
int swapNum;
while(true){
tmp = q.top();
q.pop();
if(point[tmp->left] != point[tmp->right]){
count++;
if(point[tmp->left] < point[tmp->right]){
swapNum = point[tmp->right];
for(int i = 0;i < n;i++){
if(point[i] == swapNum){
point[i] = point[tmp->left];
}
}
}
else{
swapNum = point[tmp->left];
for(int i = 0;i <n;i++){
if(point[i] == swapNum){
point[i] = point[tmp->right];
}
}
}
k[tmp->left][tmp->right] = tmp->weight;
k[tmp->right][tmp->left] = tmp->weight;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cout << k[i][j] << " ";
}
cout << endl;
}
if(q.empty() || count == n-1) break;
else cout << endl;
}
}
}
void prim(){
int **p = (int **) new int*[n];
for(int i = 0;i < n;i++){
p[i] = new int[n];
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
p[i][j] = 0;
}
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cout << p[i][j] << " ";
}
cout << endl;
}
cout << endl;
EdgeNode *tmp = new EdgeNode();
int count = 1;
int *a = new int[n];
queue<EdgeNode*> que;
for(int i = 1;i < n;i++){
a[i] = 0;
}
a[0] = 1;
while(count < n && !q.empty()){
tmp = q.top();
q.pop();
if(a[tmp->left] != a[tmp->right]){
count++;
if(a[tmp->left] == 1) a[tmp->right] = 1;
else a[tmp->left] = 1;
p[tmp->left][tmp->right] = tmp->weight;
p[tmp->right][tmp->left] = tmp->weight;
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cout << p[i][j] << " ";
}
cout << endl;
}
cout << endl;
while(!que.empty()){
q.push(que.front());
que.pop();
}
}
else{
que.push(tmp);
}
if(!que.empty() && q.empty()){
EdgeNode *tmp = new EdgeNode();
while(!que.empty()){
tmp = que.front();
q.push(tmp);
que.pop();
}
}
}
}
};
int main()
{
int n;
int **a;
cin >> n;
a = (int**) new int*[n];
for(int i = 0;i < n;i++){
a[i] = new int[n];
}
for(int i = 0;i < n;i++){
for(int j = 0;j < n;j++){
cin >> a[i][j];
}
}
MinTree *tree = new MinTree(n);
tree->init(a);
cout << "Prim:" << endl;
tree->prim();
tree->init(a);
cout << "Kruskal:" << endl;
tree->kruskal();
return 0;
}
3.迪杰斯特拉算法求最短路径
这道题由于每条边的权重都为1,所以选择用队列,用广度优先进行求解,
能过就行
代码
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
struct PointNode{
int i;
int j;
PointNode *farther;
PointNode(int _i = 0,int _j = 0,PointNode *_farther = NULL){
i = _i;
j = _j;
farther = _farther;
}
};
class Graph{
private:
int m,n;
int **a;
PointNode *start;
PointNode *end;
queue<PointNode*> q;
public:
Graph(int _m,int _n){
m = _m;
n = _n;
a = (int**) new int*[m];
for(int i = 0;i < m;i++){
a[i] = new int[n];
}
}
~Graph(){
for(int i = 0;i < m;i++){
delete a[i];
}
delete a;
}
void init(){
for(int i = 0; i < m;i++){
for(int j = 0;j < n;j++){
cin >> a[i][j];
if(a[i][j] == 3){
a[i][j] = 0;
start = new PointNode(i,j);
}
else if(a[i][j]==4){
end = new PointNode(i,j);
}
}
}
}
void minFind(){
q.push(start);
PointNode *current = new PointNode();
while(!q.empty()){
current = q.front();
q.pop();
//cout << current->i << " " << current->j << endl;
if(current->i == end->i && current->j == end->j) {
myPrint(current);
break;
}
if(current->i-1 >= 0 && a[current->i-1][current->j]!=0){
a[current->i-1][current->j] = 0;
q.push(new PointNode(current->i-1,current->j,current));
}
if(current->j+1 <= n-1 && a[current->i][current->j+1]!=0){
a[current->i][current->j+1] = 0;
q.push(new PointNode(current->i,current->j+1,current));
}
if(current->j-1 >= 0 && a[current->i][current->j-1]!=0){
a[current->i][current->j-1] = 0;
q.push(new PointNode(current->i,current->j-1,current));
}
if(current->i+1 <= m-1 && a[current->i+1][current->j]!= 0){
a[current->i+1][current->j] = 0;
q.push(new PointNode(current->i+1,current->j,current));
}
}
}
void myPrint(PointNode *n){
PointNode *current = n;
stack<PointNode*> s;
while(current->farther != NULL){
s.push(current);
current = current->farther;
}
cout << start->i << " " << start->j << endl;
while(!s.empty()){
current = s.top();
s.pop();
cout << current->i << " " << current->j << endl;
}
}
};
int main()
{
int m,n;
cin >> m >> n;
Graph *g = new Graph(m,n);
g->init();
g->minFind();
return 0;
}
4.拓扑排序判断是否有环
通过farther数组存放入度
child二维数组存放指出的边所对应的顶点
代码
#include <iostream>
using namespace std;
class Graph{
private:
int n;
int restNum;
int *farther;
int **child;
public:
Graph(int _n){
n = _n;
restNum = n;
farther = new int[n];
child = (int**)new int*[n];
for(int i = 0;i < n;i++){
child[i] = new int[n];
}
for(int i = 0;i < n;i++){
farther[i] = 0;
for(int j = 0;j < n;j++){
child[i][j] = -1;
}
}
}
~Graph(){
delete farther;
for(int i = 0; i < n;i++){
delete child[i];
}
delete child;
}
void init(){
int a;
for(int i = 0; i < n;i++){
for(int j = 0;j < n;j++){
cin >> a;
if(a != 0){
farther[j]++;
child[i][j] = j;
}
}
}
}
int farNum(){
int num = 0;
for(int i = 0;i < n;i++){
if(farther[i] == 0) num++;
}
return num;
}
void TopSort(){
while(farNum() > 0){
int k = -1;
for(int i = 0;i < n;i++){
if(farther[i] == 0) {
k = i;
farther[i] = -1;
restNum--;
break;
}
}
if(k >= 0){
for(int i = 0; i < n;i++){
if(child[k][i]>0){
farther[i]--;
child[k][i] = -1;
}
}
}
}
if(restNum==0) cout << "NO" << endl;
else cout << "YES" << endl;
return;
}
};
int main()
{
int n;
cin >> n;
Graph *g = new Graph(n);
g->init();
g->TopSort();
return 0;
}
2021.12.4