拓扑排序及关键应用

问题 B: 图综合练习–拓扑排序

题目描述

已知有向图,顶点从0开始编号,求它的拓扑有序序列。

拓扑排序算法:给出有向图邻接矩阵
1.逐列扫描矩阵,找出入度为0且编号最小的顶点v

2.输出v,并标识v已访问

3.把矩阵第v行全清0

重复上述步骤,直到所有顶点输出为止

–程序要求–

若使用C++只能include一个头文件iostream;若使用C语言只能include一个头文件stdio
程序中若include多过一个头文件,不看代码,作0分处理
不允许使用第三方对象或函数实现本题的要求

输入

第一行输入一个整数t,表示有t个有向图

第二行输入n,表示图有n个顶点

第三行起,输入n行整数,表示图对应的邻接矩阵

扫描二维码关注公众号,回复: 13112457 查看本文章

以此类推输入下一个图的顶点数和邻接矩阵

输出

每行输出一个图的拓扑有序序列

样例输入

2
5
0 1 0 1 1
0 0 1 0 0
0 0 0 0 1
0 0 1 0 0
0 0 0 0 0
7
0 0 0 0 0 0 0
1 0 1 1 0 0 0
1 0 0 0 0 0 0
1 0 1 0 0 0 0
0 0 0 0 0 1 1
0 1 0 0 0 0 0
0 0 0 1 0 1 0

样例输出

0 1 3 2 4
4 6 5 1 3 2 0

代码

#include <iostream>
#define N 10;
using namespace std;

class solution
{
    
    
public:
    int graph[10][10];
    int num;
    bool visit[10];
    void initial()
    {
    
    
        cin >> num;
        for(int i=0;i<num;i++){
    
    
            visit[i]=false;
            for(int j=0;j<num;j++)
                cin >> graph[i][j];
        }
    }
    void toporder()
    {
    
    
        int v;
        for(int k=0;k<num;k++){
    
    
            for(int j=0;j<num;j++){
    
    //找到入度为0的节点
                if(visit[j])continue;
                bool flag=false;
                for(int i=0;i<num;i++){
    
    
                    if(graph[i][j]==1){
    
    
                        flag=false;
                        break;
                    }
                    flag=true;
                }
                if(flag){
    
    v=j;break;}
            }
            visit[v]=true;
            cout << v << ' ';
            for(int j=0;j<num;j++)
                graph[v][j]=0;
        }
        cout << endl;
    }
};

int main()
{
    
    
    int t;
    cin >> t;
    while(t--){
    
    
        solution task;
        task.initial();
        task.toporder();
    }
}

问题 D: 关键路径-STL版

题目描述

给定有向图无环的边信息,求每个顶点的最早开始时间、最迟开始时间。

// 参考代码

#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;

class Vertex {
    
    
public:
    int indexNo;
    bool hasEnterQueue;
    int early;
    int later;

    Vertex(int indexNo) {
    
    
        this->indexNo = indexNo;
        this->hasEnterQueue = false;
        early = -1;
        later = 0x7FFFF;
    }
    void updateEarly(int parentEarly, int edgeValue) {
    
    
        int newEarly = parentEarly + edgeValue;
        if (newEarly > this->early)
            this->early = newEarly;
    }
    void updateLater(int childLater, int edgeValue) {
    
    
        int newLater = childLater - edgeValue;
        if (newLater < this->later)
            this->later = newLater;
    }
};


class Graph {
    
    
public:
    vector<Vertex> vertexes;
    vector<vector<int> > adjMat;
    int n;
public:
    void readVertexes() {
    
    
        //TODO: 将顶点数读入成员变量n
        
        //TODO: 从输入初始化vertexes数组
        int i=0;
        for(; i<n; ++i) {
    
    
            Vertex v(i);
            this->vertexes.push_back(v);
        }
        
        //为成员变量adjMat创建内存,赋初值
        for(i=0; i<n; ++i) {
    
    
            vector<int> row;
            int j=0;
            for(; j<n; ++j) {
    
    
                //TODO: 将0增加到row最后
            }
           //TODO: 将row增加到adjMat最后
        }
    }
    void readAdjMatrix() {
    
    
        //read the adjacent info into this->adjMat
        int edges;
        cin >> edges;
        int i=0;
        int s, t, w;  //s源顶点编号,t目的顶点编号,w边长
        for(; i<edges; ++i) {
    
    
            //TODO: 读入s,t,w,并将adjMat的第s行、第t列的值改为w.
        }
    }

    void updateEarly(int parentNo, queue<int>& earlyQue) {
    
    
        int parentEarly = vertexes[parentNo].early;  //读入父结点early值

        int j=0;
        for(; j<n; ++j) {
    
    
            int edgeValue = adjMat[parentNo][j];
            if (edgeValue == 0) continue;  //若父结点与结点j没有边相连,pass

            Vertex& child = vertexes[j];
            child.updateEarly(parentEarly, edgeValue); //更新子结点j的early信息

            if(!child.hasEnterQueue) {
    
    
                child.hasEnterQueue = true; //将子结点加入队列
                earlyQue.push(j);
            }
        }
    }
    void updateLater(int childNo, queue<int>& laterQue) {
    
    
        //TODO:
    }

    int getRoot() {
    
    
        //获取入度为0的顶点
        int j=0;
        for(; j<n; ++j) {
    
    
            int i=0;
            for(; i<n && adjMat[i][j] == 0; ++i);
            if (i>=n) return j; //j has not any in-edges.
        }
        return -1;  //表示没找到
    }
    int getLeaf() {
    
    
        //TODO: 获取出度为0的顶点
    }

    void printEarlyLater(bool isEarly) {
    
    
        int i=0;
        for(; i<n; ++i) {
    
    
            Vertex& v = vertexes[i];
            if (isEarly)
                cout << v.early << " ";
            else {
    
    
                cout << v.later << " ";
            }
        }
        cout << endl;
    }

    void findEarly() {
    
    
        //执行关键路径算法,求每个顶点的最早开始时间。
        int r = getRoot();
        Vertex& root = vertexes[r];
        root.hasEnterQueue = true;
        root.early = 0;

        queue<int> que;
        que.push(r);

        while(!que.empty()) {
    
    
            int p = que.front();
            que.pop();

            updateEarly(p, que);
        }

        printEarlyLater(true);
    }
    void clearEnterQueue() {
    
    
        int i=0;
        for(; i<n; ++i) {
    
    
            vertexes[i].hasEnterQueue = false;
        }
    }
    void findLater() {
    
    
        //TODO:调用clearEnterQueue,以清除每个顶点的hasEnterQueue=false
        //执行关键路径算法,求每个顶点的最迟开始时间。
    }

    void main() {
    
    
        readVertexes();
        readAdjMatrix();
        findEarly();
        findLater();
    }
};


int main() {
    
    
    int t=1;
    //cin >> t;
    while (t--) {
    
    
        Graph g;
        g.main();
    }
    return 0;
}

输入

第一行图的顶点总数

第二行边的总数

第三行开始,每条边的时间长度,格式为源结点 目的结点 长度

输出

第一行:第个顶点的最早开始时间

第二行:每个顶点的最迟开始时间

样例输入

9
12
0 1 3
0 2 10
1 3 9
1 4 13
2 4 12
2 5 7
3 6 8
3 7 4
4 7 6
5 7 11
6 8 2
7 8 5
样例输出
0 3 10 12 22 17 20 28 33
0 9 10 23 22 17 31 28 33

代码

#include <iostream>
#include <vector>
#include <string>
#include <queue>
using namespace std;

class Vertex {
    
    
public:
    int indexNo;
    bool hasEnterQueue;
    int early;
    int later;
    Vertex(int indexNo) {
    
    
        this->indexNo = indexNo;
        this->hasEnterQueue = false;
        early = -1;
        later = 0x7FFFF;
    }
    void updateEarly(int parentEarly, int edgeValue) {
    
    
        int newEarly = parentEarly + edgeValue;
        if (newEarly > this->early)
            this->early = newEarly;
    }
    void updateLater(int childLater, int edgeValue) {
    
    
        int newLater = childLater - edgeValue;
        if (newLater < this->later)
            this->later = newLater;
    }
};


class Graph {
    
    
public:
    vector<Vertex> vertexes;
    vector<vector<int> > adjMat;
    int n;//顶点数
public:
    void readVertexes() {
    
    
        //将顶点数读入成员变量n
        cin >> n;
        //从输入初始化vertexes数组
        for(int i=0;i<n; ++i) {
    
    
            Vertex v(i);
            this->vertexes.push_back(v);
        }
        
        //为成员变量adjMat创建内存,赋初值
        for(int i=0; i<n; ++i) {
    
    
            vector<int> row;
            int j=0;
            for(; j<n; ++j) {
    
    
                row.push_back(0);
                //将0增加到row最后
            }
            adjMat.push_back(row);
           //将row增加到adjMat最后
        }
    }
    void readAdjMatrix() {
    
    
        //read the adjacent info into this->adjMat
        int edges;
        cin >> edges;
        int i=0;
        int s, t, w;  //s源顶点编号,t目的顶点编号,w边长
        for(; i<edges; ++i) {
    
    
            cin >> s >> t >> w;
            adjMat[s][t]=w;
            //读入s,t,w,并将adjMat的第s行、第t列的值改为w.
        }
    }

    void updateEarly(int parentNo, queue<int>& earlyQue) {
    
    
        int parentEarly = vertexes[parentNo].early;  //读入父结点early值
        for(int j=0; j<n; ++j) {
    
    
            int edgeValue = adjMat[parentNo][j];
            if (edgeValue == 0) continue;  //若父结点与结点j没有边相连,pass
            Vertex& child = vertexes[j];
            child.updateEarly(parentEarly, edgeValue); //更新子结点j的early信息
            if(!child.hasEnterQueue) {
    
    
                child.hasEnterQueue = true; //将子结点加入队列
                earlyQue.push(j);
            }
        }
    }
    void updateLater(int childNo, queue<int>& laterQue) {
    
    
        //TODO:
    }

    int getRoot() {
    
    //获取入度为0的顶点
        for(int j=0; j<n; ++j)
            for(int i=0; i<n && adjMat[i][j] == 0; ++i)
                if (i>=n) return j; //j has not any in-edges.
        return -1;  //表示没找到
    }
    int getLeaf() {
    
    //获取出度为0的顶点
        for(int i=0;i<n;++i)
            for(int j=0;j<n&&adjMat[i][j]==0;++j)
                if(j>=n)return i;
        return -1;
    }

    void printEarlyLater(bool isEarly) {
    
    
        int i=0;
        for(; i<n; ++i) {
    
    
            Vertex& v = vertexes[i];
            if (isEarly)
                cout << v.early << " ";
            else {
    
    
                cout << v.later << " ";
            }
        }
        cout << endl;
    }

    void findEarly() {
    
    
        //执行关键路径算法,求每个顶点的最早开始时间。
        int r = getRoot();
        Vertex& root = vertexes[r];
        root.hasEnterQueue = true;
        root.early = 0;

        queue<int> que;
        que.push(r);

        while(!que.empty()) {
    
    
            int p = que.front();
            que.pop();

            updateEarly(p, que);
        }

        printEarlyLater(true);
    }
    void clearEnterQueue() {
    
    
        int i=0;
        for(; i<n; ++i) {
    
    
            vertexes[i].hasEnterQueue = false;
        }
    }
    // void findLater() {
    
    
    //     //TODO:调用clearEnterQueue,以清除每个顶点的hasEnterQueue=false
    //     //执行关键路径算法,求每个顶点的最迟开始时间。
    // }
    void findLater()                //执行关键路径算法,求每个顶点的最玩开始时间。
    {
    
    
        clearEnterQueue();
        int r = getLeaf();
        Vertex &parent = vertexes[r];
        parent.hasEnterQueue = true;
        parent.later = parent.early;
 
        queue<int> que;
        que.push(r);
 
        while(!que.empty())
        {
    
    
            int p = que.front();
            que.pop();
 
            updateLater(p,que);
        }
        printEarlyLater(false);
    }
    void main() {
    
    
        readVertexes();
        readAdjMatrix();
        findEarly();
        findLater();
    }
};


int main() {
    
    
    int t=1;
    //cin >> t;
    while (t--) {
    
    
        Graph g;
        g.main();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/NP_hard/article/details/111084748