hdu 4109 拓扑排序 关键路径

Instrction Arrangement

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1266    Accepted Submission(s): 524


Problem Description
Ali has taken the Computer Organization and Architecture course this term. He learned that there may be dependence between instructions, like WAR (write after read), WAW, RAW.
If the distance between two instructions is less than the Safe Distance, it will result in hazard, which may cause wrong result. So we need to design special circuit to eliminate hazard. However the most simple way to solve this problem is to add bubbles (useless operation), which means wasting time to ensure that the distance between two instructions is not smaller than the Safe Distance.
The definition of the distance between two instructions is the difference between their beginning times.
Now we have many instructions, and we know the dependent relations and Safe Distances between instructions. We also have a very strong CPU with infinite number of cores, so you can run as many instructions as you want simultaneity, and the CPU is so fast that it just cost 1ns to finish any instruction.
Your job is to rearrange the instructions so that the CPU can finish all the instructions using minimum time.
 

Input
The input consists several testcases.
The first line has two integers N, M (N <= 1000, M <= 10000), means that there are N instructions and M dependent relations.
The following M lines, each contains three integers X, Y , Z, means the Safe Distance between X and Y is Z, and Y should run after X. The instructions are numbered from 0 to N - 1.
 

Output
Print one integer, the minimum time the CPU needs to run.
 

Sample Input
  
  
5 2 1 2 1 3 4 1
 

Sample Output
  
  
2
Hint
In the 1st ns, instruction 0, 1 and 3 are executed; In the 2nd ns, instruction 2 and 4 are executed. So the answer should be 2.
解析:解决这个问题是要求出某个活动所用的最长时间,因为一个活动可能必须在另一个活动完成之后w时间内才能完成,所以整个工程的完成是在某个点完成之后才能完成,只要求出这个点所用的时间就是整个工程所用的时间
由此题来学习关键路径:

AOE

在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在带权有向图中若以顶点表示事件,有向边表示活动,边上的权值表示该活动持续的时间,这样的图简称为AOE,如下图。

 

AOE网具有以下性质:

1)只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。

2)只有在进入某点的各有向边所代表的活动都已结束,该顶点所代表的时事件才能发生。

可以将上图假想一个工程有6项活动,网中5个顶点,分别表示5个事件,边上的权值分别表示各项活动所需要的时间,事件v1表示工程开始,事件v3表示活动34完成后,活动5可以开始,事件v4表示活动2完成活动4和活动6开始,v5表示活动1完成活动3开始,事件v2表示工程结束。

关键路径及其算法

1.关键路径:

AOE网中所关心的问题是完成整个工程至少需要多少时间和哪些活动是影响整个工程进度的关键。

由于AOE网中的某些活动能够平行地进行,故完成整个工程所需的时间是从开始顶点到结束顶点的最长路径长度(路径上的权值和)最长路径叫关键路径。如上述工程的关键路径是1->4->3->2,关键路径长度为2+7+6=15,关键活动是a2a4a5

代码模板:时间很长

M:1952 T:1252

#include<iostream>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 1010;
const int M = 10010;
int n, m, head[N], degree[N];
struct p
{
	int to, from, next, w;
}edge[M];
void topo()
{
	queue<int>q;
	int temp[N];
	int time[N];
	memset(time, 0, sizeof(time));
	int count0=0,flag=0;
	for(int i=0;i<n;i+=count0){
        count0=0;
        for(int j=0;j<n;j++)
        if(degree[j]==0){
            temp[count0++]=j;
            degree[j]--;
            if(flag==0)time[j]=1;
        }
        flag++;
        for(int j=0;j<count0;j++){
        int u=temp[j];
        for(int k=head[u];k!=-1;k=edge[k].next){
           int v = edge[k].to;
			int w = edge[k].w;
			time[v] = max(time[v], time[u] + w);
			degree[v]--;
        }
        }
	}
	/*for (int i = 0; i < n;i++)
	if (degree[i] == 0){
		q.push(i);
		time[i] = 1;
	}
	while (!q.empty()){
		int u = q.front();
		q.pop();
		for (int k = head[u]; k != -1; k = edge[k].next){
			int v = edge[k].to;
			int w = edge[k].w;
			time[v] = max(time[v], time[u] + w);
			degree[v]--;
			if (!degree[v])q.push(v);
		}
	}
	*/
	int maxn = 0;
	for (int i = 0; i < n; i++)
		maxn = max(time[i], maxn);
	cout << maxn << endl;

}
int main()
{
	while (cin >> n >> m){
		memset(head, -1, sizeof(head));
		memset(degree, 0, sizeof(degree));
		int u, v, w;
		for (int i = 0; i < m; i++){
			cin >> u >> v >> w;
			edge[i].from = u;
			edge[i].to = v;
			edge[i].w = w;
			edge[i].next = head[u];
			head[u] = i;
			degree[v]++;
		}
		topo();
	}
}

一下使用队列来存储入度为0的点:

M:1856 T:826

#include<iostream>
#include<string.h>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
#define N 1010
#define M 10010
int n,m,head[N],degree[N];
struct p
{
    int to,from,next,w;
}edge[M];
void topo()
{
    queue<int>q; 
    int time[N];
    memset(time,0,sizeof(time));
    for(int i=0;i<n;i++)
    if(degree[i]==0){
        q.push(i);
        time[i]=1;
    }
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v=edge[k].to;
            int w=edge[k].w;
            time[v]=max(time[v],time[u]+w);
            degree[v]--;
            if(!degree[v])q.push(v);
        }
    }
    int maxn=0;
     for(int i=0;i<n;i++){
            maxn=max(time[i],maxn);
        }
        cout<<maxn<<endl;
}
int main()
{
    while(cin>>n>>m){
        memset(head,-1,sizeof(head));
        memset(degree,0,sizeof(degree));
        int u,v,w;
        for(int i=0;i<m;i++){
            cin>>u>>v>>w;
            edge[i].from=u;
            edge[i].to=v;
            edge[i].next=head[u];
            head[u]=i;
            degree[v]++;
            edge[i].w=w;
        }
        topo();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值