本实验项目是实验项目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