西工大数据结构理论NOJ6,图的应用

 

#include <iostream>
using namespace std;
#define MAXSIZE 100
struct graph
{
    int n, m;
    int verx[MAXSIZE] = { 0 };
    int arc[MAXSIZE][MAXSIZE] = { 0 };
};
int visited[MAXSIZE] = { 0 };
void dfs(graph& G, int j)
{
    visited[j] = 1;
    for (int i = 1; i <= G.n; i++) {
        if (G.arc[j][i] && !visited[i]) {
            dfs(G, i);
        }
    }
}
bool isreach(graph& G, int i, int j)
{
    if (G.arc[i][j] == 1)
        return true;
    dfs(G, i);
    return visited[j];
}
void creatgraph(graph& G)
{
    cin >> G.n >> G.m;//n个顶点,m条边
    for (int i = 1; i <= G.n; i++)
        cin >> G.verx[i];
    int i, j;
    for (int k = 1; k <= G.m; k++)
    {
        cin >> i >> j;
        G.arc[i][j] = 1;
    }
}
int main()
{
    graph G;
    creatgraph(G);
    int i, j;
    cin >> i >> j;//j、i为两个顶点
    if (isreach(G, i, j))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    return 0;
}

定义了一个 visited 数组用来记录顶点是否被访问过,以判断两个顶点之间是否存在路径。dfs 函数是一个深度优先搜索函数,用来遍历与当前节点相邻的节点。在 isreach 函数中,如果两个顶点之间有直接的连通关系,则返回 true;否则,遍历从起始顶点 i 可以到达的所有顶点,判断终止顶点 j 是否被访问过,如果被访问过,则说明存在一条路径从 ij,返回 true;否则返回 false。感觉深搜就短短几行代码,还挺废脑子的!

 

#include<iostream>
using namespace std;
#define MAXSIZE 100
#include<queue>
struct graph
{
    int n, m;
    int verx[MAXSIZE] = { 0 };
    int arc[MAXSIZE][MAXSIZE] = { 0 };
};
int visited[MAXSIZE] = { 0 };
queue<int>Q;
bool isreach(graph& G, int s, int e)
{
    if (G.arc[s][e] == 1)
        return true;
    visited[s] = 1;
    Q.push(s);
    while (!Q.empty())
    {
        int i = Q.front();
        for (int k = 1; k <= G.n; k++)
        {
            if (G.arc[i][k] != 0 && !visited[k])
            {
                visited[k] = 1;
                Q.push(k);
                if (k == e)
                    return true;
            }
        }
        Q.pop();
    }
    return false;
}
void creatgraph(graph& G)
{
    cin >> G.n >> G.m;//n个顶点,m条边
    for (int i = 1; i <= G.n; i++)
        cin >> G.verx[i];
    int i, j;
    for (int k = 1; k <= G.m; k++)
    {
        cin >> i >> j;
        G.arc[i][j] = 1;
    }
}
int main()
{
    graph G;
    creatgraph(G);
    int i, j;
    cin >> i >> j;//j、i为两个顶点
    if (isreach(G, i, j))
        cout << "yes" << endl;
    else
        cout << "no" << endl;
    return 0;
}

我一直坚持使用C++的原因就是栈和队列不用自己写!!!

广搜和深搜图的建立部分大差不差,主要是思想,这里使用队列存储已经访问过的节点,每从队列中出来一个节点,就把它相邻且没有访问过的节点进入队列。(有些小伙伴可能坚持栈和队列这些结构自己写,我本人觉得真没必要,你写的再好都不如人家用现成的快,所以在上机考试还是算法训练这些场景里我还是建议大家直接用现成的)

#include<iostream>
using namespace std;
#include<stack>
stack<char>op;
bool judge(char a, char b)//b是栈顶元素,a的优先级大返回真
{
    if (b == '(')
        return true;
    if (a == '+' || a == '-')
        return false;
    if (b == '*' || b == '/')
        return false;
    return true;
}
void nibolan(string s)
{
    for (int i = 0; i < s.length(); i++)
    {
        if (s[i] >= 'a' && s[i] <= 'z')
            cout << s[i];
        else if (s[i] == '(')
            op.push(s[i]);
        else if (s[i] == ')')
        {
            while (!op.empty() && op.top() != '(')
            {
                cout << op.top();
                op.pop();
            }
            op.pop();
        }
        else
        {
            if (op.empty() || judge(s[i], op.top()))//空栈或者栈顶元素的优先级小
            {
                op.push(s[i]);
            }
            else
            {
                while (!op.empty()&&!judge(s[i],op.top()))//栈非空并且栈顶元素优先级大
                {
                    cout << op.top();
                    op.pop();
                }
                op.push(s[i]);
            }
        }
    }
    while (!op.empty())
    {
        cout << op.top();
        op.pop();
    }
}
int main()
{
    string s;
    cin >> s;
    nibolan(s);
    return 0;
}

 

//迪杰斯特拉算法
#include<iostream>
#include<cstring>
#define MAXSIZE 100
#define INF 0x0f3f3f3f    // 定义无穷大常量
using namespace std;
struct graph {
    int verx[MAXSIZE];
    int arc[MAXSIZE][MAXSIZE];
    int n, m;
};
int dist[MAXSIZE];
int visited[MAXSIZE];
void dijkstra(graph& G, int start)
{
    memset(visited, 0, sizeof(visited));
    memset(dist, INF, sizeof(dist));
    for (int i = 1; i <= G.n; i++)
        dist[i] = G.arc[start][i];
    visited[start] = 1;
    for (int i = 1; i < G.n; i++)//对所有节点进行n-1次循环
    {
        int flag = 0;
        int mindist = INF;
        int v = i + 1, j;
        for (j = 1; j <= G.n; j++)//找出一个距离最小的节点
        {
            if (!visited[j] && dist[j] < mindist)
            {
                flag = 1;
                mindist = dist[j];
                v = j;
            }
        }
        visited[v] = 1;
        if (flag)
            cout << 1 << " " << v << " " << dist[v] << endl;
        else
            cout << 1 << " " << v << " " << -1 << endl;
        for (int j = 1; j <= G.n; j++)
        {
            if (!visited[j] && G.arc[v][j] < INF && dist[j] > dist[v] + G.arc[v][j])
                dist[j] = dist[v] + G.arc[v][j];
        }
    }
}
void creategraph(graph& G)
{
    cin >> G.n >> G.m;
    memset(G.arc, INF, sizeof(G.arc));
    for (int i = 1; i <= G.n; i++)
    {
        G.verx[i] = i;
    }
    int x, y, w;
    for (int j = 1; j <= G.m; j++)
    {
        cin >> x >> y >> w;
        G.arc[x][y] = w;
    }
}
int main()
{
    graph G;
    creategraph(G);
    dijkstra(G, 1);
    return 0;
}

 第一次写迪杰斯特拉算法,忘记把有边的权重设置为无穷大了,这里一定要记得用memset函数置数组的值,还有就是不可达的节点输出-1,这个可让我纠结了大半天,最终选择立一个flag,如果flag为1,就说明找到了最小的路径,如果没有找到最小的路径,就说明当前节点不可达,就可以输出-1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值