关键路径-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<cstring>
#include<queue>
#include<stack>
using namespace std;
#define INF 0x7f
void display(int m[INF][INF],int n)
{
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            cout<<m[i][j]<<" ";
        }
        cout<<endl;
    }
}
 
 
int findmax(int count,int *a)
{
    int maxx=-1;
    for(int i=0;i<count;i++)
    {
        if(a[i]>maxx)
            maxx=a[i];
    }
    return maxx;
}
int findmin(int count,int *a)
{
    int minn=0x3f3f3f3f;
    for(int i=0;i<count;i++)
    {
        if(a[i]<minn)
            minn=a[i];
    }
    return minn;
}
 
int main()
{
    int n;
    int e;
    cin>>n>>e;
    int m[INF][INF];
    memset(m,0,sizeof(m));
    for(int i=0;i<e;i++)
    {
        int x,y,num;
        cin>>x>>y>>num;
        m[x][y]=num;
    }
    int closem[INF][INF];
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            if(m[i][j]!=0)
            {
                closem[i][j]=1;
            }
            else
                closem[i][j]=0;
        }
    }
    int number=n;
    int visited[INF]={0};
    queue<int>tuopu;
    while(number--)
    {
        for(int i=0;i<n;i++)
        {
            int indegree=0;
            for(int j=0;j<n;j++)
            {
                indegree+=closem[j][i];
            }
            if(indegree==0&&visited[i]==0)
            {
                visited[i]=1;
                tuopu.push(i);
                for(int k=0;k<n;k++)
                {
                    if(closem[i][k]>0)
                        closem[i][k]--;
                }
            }
        }
    }
    queue<int>tuopu1=tuopu;
    queue<int>tuopu2=tuopu1;
    int ve[INF];
    ve[tuopu.front()]=0;
    tuopu.pop();
    while(!tuopu.empty())
    {
        int save[INF]={0};
        int count=0;
        for(int i=0;i<n;i++)
        {
            if(m[i][tuopu.front()]>0)
            {
                save[count]=ve[i]+m[i][tuopu.front()];
                count++;
            }
        }
        ve[tuopu.front()]=findmax(count,save);
        tuopu.pop();
    }
 
    stack<int>nituopu1;
    while(!tuopu1.empty())
    {
        nituopu1.push(tuopu1.front());
        tuopu1.pop();
    }
    queue<int>nituopu;
    while(!nituopu1.empty())
    {
        nituopu.push(nituopu1.top());
        nituopu1.pop();
    }
 
    int vl[INF];
    vl[nituopu.front()]=ve[nituopu.front()];
    nituopu.pop();
    while(!nituopu.empty())
    {
        int save[INF]={0};
        int count=0;
        for(int j=0;j<n;j++)
        {
            if(m[nituopu.front()][j]>0)
            {
                save[count]=vl[j]-m[nituopu.front()][j];
                count++;
            }
        }
        vl[nituopu.front()]=findmin(count,save);
            nituopu.pop();
    }
    for(int i=0;i<n;i++)
    {
        cout<<ve[i]<<" ";
    }
    cout<<endl;
    for(int i=0;i<n;i++)
    {
        cout<<vl[i]<<" ";
    }
    cout<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/SZU-DS-wys/p/12182934.html