问题 F: 图-节点的最早发生时间

题目描述

下图是一个有向无环图,节点内的数字表示该节点的序号,节点之间的连接线表示节点之间的连接方式,连接线上方的黑色数字表示该连接线的权重。
最早发生时间:从前往后,前驱节点到当前节点所需时间,取最大值
本题要求:求出有向无环图中每一个节点的最早发生时间(示例图中每一个节点的最早发生时间以节点上方的黄色数字标出)

 

输入格式

第一行为2个正整数m和n,分别表示有向无环图的节点个数和边的数量。
接下来n行,代表n条边。分别是起点、终点、权重,以空格分隔。
(m<50,n<100)

输出格式

按行输出有向无环图中每一个节点最早发生时间,按照节点的序号从小到大输出。
如样例中,0、1、2、3、4号节点的最早发生时间分别是0、3、3、7、11。
则按行输出0、3、3、7、11。

输入样例

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

输出样例  

0
3
3
7
11

数据范围与提示

 

代码展示 

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

#define INFO_MAX_SIZE 20
#define MAX_SIZE 200
 //领接矩阵存储的图
struct Graph{
	int vexNumber;
	string vexInfo[INFO_MAX_SIZE];
	int adjMatrix[MAX_SIZE][MAX_SIZE];
};
 //弧结点定义
struct ArcNode{
	int weight;//弧上的信息部分
	int adj;//邻接点的序号
	ArcNode *nextarc;
};
 //顶点结点定义
struct VexNode{
	string Info;
	ArcNode *firstarc;
};
 //领接表结构的图的定义
struct linkGraph{
	VexNode *vexes;
	int vexnumber;
};

struct tempNode{
	int col;
	int row;
	int weight;
	//tempNode *next;
};

struct temp{
	int num;
	tempNode *docu;
};


int preInitGraph(linkGraph &G,const Graph &g){
	G.vexes=new VexNode[g.vexNumber];
	G.vexnumber=g.vexNumber;
	for(int i=0;i<g.vexNumber;i++){
		G.vexes[i].firstarc=NULL;
	}
	return 0;
}
//将邻接矩阵存储的图转换为领接表存储的图
void InitGraph(linkGraph &G,const Graph &g,temp &t){
	preInitGraph(G,g);
	for(int i=0;i<t.num;i++){
		int a,b,c;
		a=t.docu[i].row;b=t.docu[i].col;c=t.docu[i].weight;
		ArcNode *p=new ArcNode();
		p->nextarc=NULL;
		p->weight=c;
		p->adj=b;
		ArcNode *q=G.vexes[a].firstarc;
		if(G.vexes[a].firstarc==NULL)
			G.vexes[a].firstarc=p;
		else{
			while(q->nextarc!=NULL){
				q=q->nextarc;
			}
			q->nextarc=p;
		}
	}
}

int TopologicalSort(linkGraph LG,int Topo[]){
	vector<int>indegree(LG.vexnumber);
	for(int i=0;i<LG.vexnumber;i++) indegree[i]=0;
	for(int i=0;i<LG.vexnumber;i++){
		for(ArcNode *p=LG.vexes[i].firstarc;p!=nullptr;p=p->nextarc)
			indegree[p->adj]++;
	}
	//入度为零的点入栈
	stack<int>s;
	for(int i=0;i<LG.vexnumber;i++){
		if(indegree[i]==0)  s.push(i);
	}

	int i=0;
	while(!s.empty()){
		int j=s.top();s.pop();
		Topo[i++]=j;
		//将Vj邻接点入度减一,减为0的入栈
		for(ArcNode *p=LG.vexes[j].firstarc;p!=nullptr;p=p->nextarc){
			indegree[p->adj]--;
			if(indegree[p->adj]==0)  s.push(p->adj);
		}
	}
	if(i==LG.vexnumber)  return 0;
	else  return 1;
}

//输出领接表存储的图
void PrintGraph(const linkGraph &G){
	for(int i=0;i<G.vexnumber;i++){
		cout<<G.vexes[i].Info;
		ArcNode *p=G.vexes[i].firstarc;
		cout<<i;
		while(p!=NULL){
			cout<<" --> "<<p->adj;
			p=p->nextarc;
		}
		cout<<endl;
	}
}


vector<pair<int,int>> CriticalPath(linkGraph G){
	vector<pair<int,int>>aArcs;
	//统计入度
	vector<int>indegree(G.vexnumber);
	for(int i=0;i<G.vexnumber;i++)  indegree[i]=0;
	for(int i=0;i<G.vexnumber;i++){
		for(ArcNode *p=G.vexes[i].firstarc;p!=nullptr;p=p->nextarc)
			indegree[p->adj]++;
	}
	//入度为0进栈
	stack<int>s;
	for(int i=0;i<G.vexnumber;i++){
		if(indegree[i]==0)  s.push(i);
	}
	//拓扑排序,计算ve
	vector<int>ve(G.vexnumber);
	for(int i=0;i<G.vexnumber;i++) ve[i]=0;
	stack<int>s2;//记录拓扑序
	while(!s.empty()){
		int i=s.top();s.pop();
		s2.push(i);

		//遍历Vi邻接点
		for(ArcNode *p=G.vexes[i].firstarc;p!=nullptr;p=p->nextarc){
			//邻接点入度减一,为0入栈
			int j=p->adj;
			indegree[j]--;
			if(indegree[j]==0)  s.push(j);
			//修正Vj的Ve值
			if(ve[i]+p->weight>ve[j]){
				ve[j]=ve[i]+p->weight;
			}
		}
		//按逆拓扑序计算vl,终点的ve值作为vl的初值
		vector<int>vl(G.vexnumber);
		int maxve=ve[s2.top()];
		for(int i=0;i<G.vexnumber;i++) vl[i]=maxve;
		while(!s2.empty()){
			int i=s2.top();s2.pop();
			//用Vi的邻接点来修正Vi的Vl值
			for(ArcNode *p=G.vexes[i].firstarc;p!=nullptr;p=p->nextarc){
				int j=p->adj;
				if(vl[j]-p->weight<vl[i])
					vl[i]=vl[j]-p->weight;
			}
		}
		//遍历所有弧,计算弧的e和l值,挑选关键弧(e和l相等的弧)
		for(int i=0;i<G.vexnumber;i++){
			for(ArcNode *p=G.vexes[i].firstarc;p!=nullptr;p=p->nextarc){
				int e=ve[i];
				int l=vl[p->adj]-p->weight;
				if(e==l)
					//记录一条关键弧
					aArcs.push_back(make_pair(i,p->adj));
			}
		}
	}

    //本题输出在这里呀
	for(int i=0;i<G.vexnumber;i++){
			cout<<ve[i]<<endl;
	}

	return aArcs;
}


int main(){
	//freopen("/config/workspace/test/test","r",stdin);
	int n,m;
	cin>>n>>m;

	Graph G;
	G.vexNumber=n;
	temp t;
	t.num=m;
	t.docu=new tempNode[m];
	for(int i=0;i<m;i++){
		int a,b,c;
		cin>>a>>b>>c;
		t.docu[i].row=a;
		t.docu[i].col=b;
		t.docu[i].weight=c;
	}
	linkGraph LG;
	InitGraph(LG,G,t);
	CriticalPath(LG);

	
	
	return 0;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值