进阶实验6-3.5 关键活动 (30 分)

思路:

第一步:把所有的入度为0度结点压入队列中并让earliest=0;

第二步:进行topsort,并把每个弹出队列的元素压入堆栈中,如果能更新每个弹出元素的邻接点的earliest就更新。

第三步:找出所有的earliest = 最短工期的顶点,令它们的latest = earliest。

第四步;利用堆栈反向更新每个顶点的latest。

第五步:计算每条边的灵活时间,如果等于零说明这条边是关键活动,把它输出。

?分别给出邻接表实现和邻接矩阵实现的代码:

#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#define INF 65535
#define MAXV 105
using namespace std;
int n,m,indegree[MAXV];
int flex[MAXV][MAXV];
struct ENode
{
	int w,weight;
	ENode(int _w, int _weight) : w(_w), weight(_weight) {}
};
vector<ENode> Adj[MAXV];
struct GNode
{
	int earliest,latest;
}G[MAXV];
void topsort()
{
	int v,u, cnt = 0, tlp = -1;
	queue<int> q;
	stack<int> s;
	for(v=1; v<=n; v++)
	{
		if(indegree[v]==0)
		{
			q.push(v);
			G[v].earliest = 0;
		}
	}
	while(!q.empty())
	{
		u = q.front(); q.pop(); s.push(u); cnt++; 
		for(vector<ENode>::iterator it = Adj[u].begin(); it!=Adj[u].end(); it++)
		{
			indegree[it->w]--;
			if((indegree[it->w])==0) q.push(it->w);
			if(G[it->w].earliest < G[u].earliest+it->weight)
			{
				G[it->w].earliest = G[u].earliest+it->weight;
			}
		}
	}
	if(cnt != n) { printf("0\n"); return; } 
	for(v=1; v<=n; v++)
	{
		if(G[v].earliest > tlp)
			tlp = G[v].earliest;
	}
	printf("%d\n",tlp);
	for(v=1; v<=n; v++)
	{
		if(G[v].earliest == tlp)
		{
			G[v].latest = tlp;
		}
	}
	while(!s.empty())
	{
		u = s.top(); s.pop(); //printf("u = s.top() = %d\n",u);
		for(vector<ENode>::iterator it = Adj[u].begin(); it!=Adj[u].end(); it++)
		{
			//printf("G[%d].latest = %d, it->weight = %d, G[%d].latest = %d\n",it->w,G[it->w].latest,it->weight,u,G[u].latest);
			if(G[it->w].latest - it->weight < G[u].latest)
			{
				G[u].latest = G[it->w].latest - it->weight; 
				//printf("G[%d].latest = %d\n",u,G[u].latest);
			}
		}
	}
	for(v=1; v<=n; v++)
	{
		for(vector<ENode>::iterator it = Adj[v].begin(); it != Adj[v].end(); it++)
		{
			flex[v][it->w] = G[it->w].latest - G[v].earliest - it->weight;
		}
	}
	for(v=1; v<=n; v++)
	{
		for(vector<ENode>::iterator it = Adj[v].begin(); it!=Adj[v].end(); it++)
		{
			//printf("flex[%d][%d] = %d\n",v,it->w,flex[v][it->w]);
			if(flex[v][it->w] == 0)
				printf("%d->%d\n",v,it->w);
		}
	}
}
int main()
{
	int i,v1,v2,weight,v;
	fill(indegree,indegree+MAXV,0);
	fill(flex[0],flex[0]+MAXV*MAXV,-1);
	scanf("%d%d",&n,&m);
	for(v=1; v<=n; v++)
	{
		G[v].earliest = -1;
		G[v].latest = INF;//printf("G[%d].latest = %d\n",v,G[v].latest);
	}
	//printf("G[5].latest = %d\n",G[5].latest);
	for(i=0; i<m; i++)
	{
		scanf("%d%d%d",&v1,&v2,&weight);
		Adj[v1].insert(Adj[v1].begin(),ENode(v2,weight));
		indegree[v2]++;
	}
	topsort();
	return 0;
}
#include<cstdio>
#include<queue>
#include<algorithm>
#include<stack>
#define MAXV 105
#define INF 1000000000
using namespace std;
int n,m,indegree[MAXV];
int E[MAXV][MAXV];
int F[MAXV][MAXV];
struct GNode
{
	int earliest,latest;
}G[MAXV];
void Topsort()
{
	int i,j,u,v,w,cnt=0;
	queue<int> q;
	stack<int> s;
	for(v=1; v<=n; v++)
	{
		if(indegree[v]==0)
		{
			q.push(v);
			G[v].earliest = 0;
		}
	}
	while(!q.empty())
	{
		u = q.front(); q.pop();cnt++;s.push(u); 
		for(w=1; w<=n; w++)
		{
			if(E[u][w]<INF)
			{
				indegree[w]--;
				if(indegree[w]==0) q.push(w);
				if(G[u].earliest+E[u][w]>G[w].earliest)
					G[w].earliest = G[u].earliest+E[u][w];
			}
		}
	}
	if(cnt!=n)
	{
		printf("0\n");
		return;
	}
	int wholetime = -1;
	for(v=1; v<=n; v++)
	{
		if(G[v].earliest>wholetime)
		{
			wholetime = G[v].earliest;
		}
	}
	printf("%d\n",wholetime);
	for(v=1; v<=n; v++)
	{
		if(G[v].earliest==wholetime)
			G[v].latest = G[v].earliest;
	}
	while(!s.empty())
	{
		v = s.top(); s.pop();
		for(u=1; u<=n; u++)
		{
			if(E[v][u]<INF&&(G[u].latest-E[v][u]<G[v].latest))
			{
				G[v].latest = G[u].latest-E[v][u];
			}
		}
	}
	for(i=1; i<=n; i++)
		for(j=n; j>=1; j--)
		{
			if(E[i][j]<INF)
			{
				F[i][j] = G[j].latest - G[i].earliest - E[i][j];
				if(F[i][j]==0)
					printf("%d->%d\n",i,j);
			}
		}
}
int main()
{
	int i,v1,v2,weight,v;
	fill(indegree,indegree+MAXV,0);
	fill(E[0],E[0]+MAXV*MAXV,INF);
	fill(F[0],F[0]+MAXV*MAXV,INF);
	scanf("%d%d",&n,&m);
	for(i=0; i<m; i++)
	{
		scanf("%d%d%d",&v1,&v2,&weight);
		E[v1][v2] = weight;
		indegree[v2]++;
	}
	for(v=1; v<=n; v++)
	{
		G[v].earliest = -1;
		G[v].latest = INF;
	}
	Topsort();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值