本实验项目是实验项目6-06的深化。任务调度问题中,如果还给出了完成每个子任务需要的时间,则我们可以算出完成整个工程需要的最短时间。在这些子任务中,有些任务即使推迟几天完成,也不会影响全局的工期;但是有些任务必须准时完成,否则整个项目的工期就要因此延误,这种任务就叫“关键活动”。
请编写程序判定一个给定的工程项目的任务调度是否可行;如果该调度方案可行,则计算完成整个工程项目需要的最短时间,并输出所有的关键活动。
输入格式说明:
输入第1行给出两个正整数N(<=100)和M,其中N是任务交接点(即衔接相互依赖的两个子任务的节点,例如:若任务2要在任务1完成后才开始,则两任务之间必有一个交接点)的数量,交接点按1~N编号,M是子任务的数量,依次编号为1~M。随后M行,每行给出了3个正整数,分别是该任务开始和完成涉及的交接点编号以及该任务所需的时间,整数间用空格分隔。
输出格式说明:
如果任务调度不可行,则输出0;否则第1行输出完成整个工程项目需要的时间,第2行开始输出所有关键活动,每个关键活动占一行,按格式“V->W”输出,其中V和W为该任务开始和完成涉及的交接点编号。关键活动输出的顺序规则是:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反。如下面测试用例2中,任务<5,7>先于任务<5,8>输入,而作为关键活动输出时则次序相反。
样例输入与输出:
序号 | 输入 | 输出 |
1 |
7 8 1 2 4 1 3 3 2 4 5 3 4 3 4 5 1 4 6 6 5 7 5 6 7 2 |
17 1->2 2->4 4->6 6->7 |
2 |
9 11 1 2 6 1 3 4 1 4 5 2 5 1 3 5 1 4 6 2 5 7 9 5 8 7 6 8 4 7 9 2 8 9 4 |
18 1->2 2->5 5->8 5->7 7->9 8->9 |
3 |
11 14 1 2 4 1 3 3 2 4 5 3 4 3 4 5 1 4 6 6 5 7 5 6 7 2 8 3 7 9 3 7 9 10 6 4 10 2 10 6 5 6 11 4 |
21 3->4 4->10 6->11 8->3 9->3 10->6 |
4 |
4 5 1 2 4 2 3 5 3 4 6 4 2 3 4 1 2 |
0 |
求关键路径 其实还是挺简单的 就是利用突破排序
但是 这个奇怪的输出 关键的路径 有点头疼 自己的代码写的是相当的乱 还好一次过了。。。
#include <iostream> #include <algorithm> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include<queue> #include<stack> #include<map> #include<set> using namespace std; #define lson rt<<1,l,MID #define rson rt<<1|1,MID+1,r //#define lson root<<1 //#define rson root<<1|1 #define MID ((l+r)>>1) typedef long long ll; typedef pair<int,int> P; const int maxn=3005; const int base=1000; const int inf=9999999999; const double eps=1e-5; int n,m; struct node { int to,cost; }; vector<node> G[maxn];//图的邻接表 vector<node> g[maxn];//图的逆邻接表 int d[maxn];//每个点的入度 int earlist[maxn];//每个点最早的发生时间 int last[maxn];//每个点的最迟发生时间 stack<int> ss;//拓扑排序的 逆序 bool tupo_sort() { stack<int> s; for(int i=1;i<=n;i++) { if(d[i]==0)s.push(i); } int cnt=0; while(!s.empty()) { int m=s.top(); ss.push(m); cnt++;s.pop(); for(int i=0;i<G[m].size();i++) { node tmp=G[m][i]; if(--d[tmp.to]==0)s.push(tmp.to); if(earlist[m]+tmp.cost>earlist[tmp.to]) { earlist[tmp.to]=earlist[m]+tmp.cost; } } } if(cnt<n)return false; return true; } void solve_last()//求最迟的发生时间 { int i; fill(last+1,last+n+1,*max_element(earlist+1,earlist+n+1)); while(!ss.empty()) { int m=ss.top(); ss.pop(); for(i=0;i<g[m].size();i++) { node k=g[m][i]; if(last[m]-k.cost<last[k.to]) { last[k.to]=last[m]-k.cost; } } } } struct acm//记录边 我这里是因为对付那个奇怪的输出的顺序 { int a,b; int order; int cost; }p[maxn],pp[maxn]; struct key//关键的节点 由关键节点找关键的边 { int node; int time; friend bool operator<(key a,key b) { return a.time<b.time; } }a[maxn]; bool cmp(acm a,acm b)//对付 输出的排序 { if(a.a!=b.a) return a.a<b.a; else return a.order>b.order; } int num=0; void find(key a,key b)//查找关键的边 { for(int i=0;i<m;i++) { if(p[i].a==a.node&&p[i].b==b.node&&last[p[i].a]+p[i].cost==last[p[i].b]) { pp[num++]=p[i]; } } } int main() { int i,j,k,t; cin>>n>>m; for(i=0;i<m;i++) { node e; int s; cin>>s>>e.to>>e.cost; p[i].a=s; p[i].b=e.to; p[i].order=i; p[i].cost=e.cost; G[s].push_back(e); node kk; kk.to=s; kk.cost=e.cost; g[e.to].push_back(kk); d[e.to]++; } if(!tupo_sort()) puts("0"); else { solve_last(); printf("%d\n",*max_element(earlist+1,earlist+n+1)); for(i=1,j=0;i<=n;i++) { if(last[i]==earlist[i]) { a[j].node=i; a[j++].time=last[i]; } } sort(a,a+j); for(i=0;i<j;i++) { for(k=i+1;k<j;k++) find(a[i],a[k]); } sort(pp,pp+num,cmp); for(j=0;j<num;j++) printf("%d->%d\n",pp[j].a,pp[j].b); } return 0; }
原文地址:http://blog.csdn.net/u013167299/article/details/42528039