关键路径

Date:2019-06-17 17:47:15

算法思想

 1 //Vi ---- ar ---> Vj
 2 
 3 int e[r];   //活动ar的最早开始时间
 4 int l[r];   //活动ar的最晚开始时间
 5 int ve[i];  //事件vi的最早发生时间
 6 int vl[i];  //事件vi的最晚发生时间
 7 
 8 e[r] = ve[i];   //活动ar的最早开始时间 = 事件vi的最早发生时间
 9 l[r] = vl[r]-w[r]; //活动ar的最晚开始时间 = 时间vj的最晚发生时间 - ar的边权
10 
11 
12 ve[j] = max{ve[ik] + w[rk]};  //Vj结点的最早发生时间 = Max{前驱结点Vik的最早发生时间+活动aik的边权}
13 //若解决Vj,必先解决Vi --> 拓扑排序求解ve
14 vl[i] = min(vl[jk] - w[rk]);  //Vi结点的最晚发生时间 = Min{后继结点Vjk的最晚发生时间 - 活动aik的边权}
15 //若解决Vi,必先解决Vj --> 逆拓扑排序求解vl

算法实现

 1 stack<int> topOrder;
 2 int TopologicalPath()
 3 {
 4     queue<int> q;
 5     for(int i=0; i<n; i++)
 6         if(inDegree[i]==0)
 7             q.push(i);
 8     while(!q.empty())
 9     {
10         int u = q.front();
11         q.pop();
12         topOrder.push(u);   //u加入拓扑排序
13         for(int i=0; i<adj[u].size(); i++)
14         {
15             int v = adj[u][i].v;
16             inDegree[v]--;
17             if(inDegree[v]==0)
18                 q.push(v);
19             if(ve[u]+adj[u][i].w > ve[v])
20                 ve[v] = ve[u] + adj[u][i].w;    //求解ve
21         }
22     }
23     if(topOrder.size() != n)    return false;
24     else    return true;
25 }
26 
27 vector<int> path[M];    //多条关键路径
28 int CriticalPath()
29 {
30     fill(ve, ve+n, 0);
31     if(topologicalSort() == false)
32         return -1;  //有环
33 
34     int s,t,maxLength=0;
35     for(int i=0; i<n; i++)
36         if(ve[i]==0){
37             s=i;break;  //源点,最早发生的事件
38         }
39 
40     for(int i=0; i<n; i++)
41         if(ve[i] > maxLength){
42             maxLength = ve[i];
43             t=i;        //汇点,最晚发生的事件
44         }
45     fill(vl, vl+n, maxLength);
46 
47     while(!topOrder.empty())
48     {
49         int u = topOrder.top();
50         topOrder.pop();
51         for(int i=0; i<adj[u].size(); i++)
52         {
53             int v = adj[u][i].v;
54             if(vl[v] - adj[u][v].w < vl[u])
55                 vl[u] = vl[v] - adj[u][v].w;
56         }
57     }
58 
59     for(int u=0; u<n; u++)
60     {
61         for(int i=0; i<adj[u].size(); i++)
62         {
63             int v = adj[u][i].v;
64             int w = adj[u][i].w;
65             int e = ve[u];      //活动的最早开始时间
66             int l = vl[v]-w;    //活动的最晚开始时间
67             if(e==l)
68                 path[u].push_back(v);
69         }
70     }
71 
72     printf("%d", s);
73     s=path[s][0];
74     while(s != t)
75     {
76         printf("->%d",s);   //输出一条关键路径
77         s=path[s][0];
78     }
79 
80     return ve[n-1];    //返回关键路径长度
81 }

相关练习

  • 更新后的大纲把动态规划都删除了,但关键路径还留着,虽然一直没考过,说不准哪天就考了呢。

Source:

Codeup 23132: 关键路径

题目描述

描述:

图的连接边上的数据表示其权值,带权值的图称作网。

上图可描述为顶点集为(a,b,c,d,e)

边集及其权值为(始点,终点 权值):

a b 3

a c 2 

b d 5

c d 7

c e 4

d e 6            

网的源点是入度为0的顶点,汇点是出度为0的顶点。网的关键路径是指从源点到汇点的所有路径中,具有最大路径长度的路径。上图中的关键路径为a->c->d->e,其权值之和为关键路径的长度为15。

本题的要求是根据给出的网的邻接矩阵求该网的关键路径及其长度。

输入

第一行输入一个正整数n(1<=n<=5),其代表测试数据数目,即图的数目

第二行输入x(1<=x<=15)代表顶点个数,y(1<=y<=19)代表边的条数

第三行给出图中的顶点集,共x个小写字母表示顶点

接下来每行给出一条边的始点和终点及其权值,用空格相隔,每行代表一条边。

输出

第一个输出是图的关键路径(用给出的字母表示顶点, 用括号将边括起来,顶点逗号相隔)

第二个输出是关键路径的长度

每个矩阵对应上面两个输出,两个输出在同一行用空格间隔,每个矩阵的输出占一行。

样例输入

2
5 6
abcde
a b 3
a c 2
b d 5
c d 7
c e 4
d e 6
4 5
abcd
a b 2
a c 3
a d 4
b d 1
c d 3

样例输出

(a,c) (c,d) (d,e) 15
(a,c) (c,d) 6

Code:

  1 #include<cstdio>
  2 #include<vector>
  3 #include<string>
  4 #include<map>
  5 #include<stack>
  6 #include<queue>
  7 #include<iostream>
  8 #include<algorithm>
  9 using namespace std;
 10 const int M=20;
 11 string st;
 12 map<string,int> mp;
 13 int n,m,in[M],ve[M],vl[M];
 14 struct node
 15 {
 16     int v;  //弧头
 17     int w;  //边权
 18     node(int _v,int _w): v(_v),w(_w) {}
 19 };
 20 vector<node> adj[M];
 21 stack<int> topOrder;
 22 
 23 void TopologicalSort()
 24 {
 25     queue<int> q;
 26     for(int i=0; i<n; i++)
 27         if(in[i]==0)
 28             q.push(i);
 29     while(!q.empty())
 30     {
 31         int u=q.front();
 32         topOrder.push(u);
 33         q.pop();
 34         for(int i=0; i<adj[u].size(); i++)
 35         {
 36             node v = adj[u][i];
 37             in[v.v]--;
 38             if(in[v.v]==0)
 39                 q.push(v.v);
 40             if(ve[u]+v.w > ve[v.v])
 41                 ve[v.v] = ve[u]+v.w;
 42         }
 43     }
 44 }
 45 
 46 int CriticalPath()
 47 {
 48     fill(ve,ve+n,0);
 49     TopologicalSort();
 50 
 51     int s,t,maxLength=0;
 52     for(int i=0; i<n; i++)
 53         if(ve[i]==0){
 54             s=i;break;
 55         }
 56     for(int i=0; i<n; i++)
 57         if(ve[i] > maxLength){
 58             maxLength=ve[i];t=i;
 59         }
 60     fill(vl,vl+n,maxLength);
 61 
 62     while(!topOrder.empty())
 63     {
 64         int u=topOrder.top();
 65         topOrder.pop();
 66         for(int i=0; i<adj[u].size(); i++)
 67         {
 68             node v = adj[u][i];
 69             if(vl[v.v]-v.w < vl[u])
 70                 vl[u] = vl[v.v]-v.w;
 71         }
 72     }
 73 
 74     vector<int> path[M];
 75     for(int u=0; u<n; u++)
 76     {
 77         for(int i=0; i<adj[u].size(); i++)
 78         {
 79             node v = adj[u][i];
 80             if(ve[u] == vl[v.v]-v.w)
 81                 path[u].push_back(v.v);
 82         }
 83     }
 84     while(s != t)
 85     {
 86         printf("(%c,%c) ", st[s],st[path[s][0]]);
 87         s=path[s][0];
 88     }
 89 
 90     return ve[n-1];
 91 }
 92 
 93 int main()
 94 {
 95 #ifdef ONLINE_JUDGE
 96 #else
 97     freopen("Test.txt", "r", stdin);
 98 #endif // ONLINE_JUDGE
 99 
100     string c1,c2;
101     int k,v1,v2,w;
102     scanf("%d", &k);
103     while(k--)
104     {
105         for(int i=0; i<M; i++)
106             adj[i].clear();
107         fill(in,in+M,0);
108 
109         scanf("%d%d", &n,&m);
110         cin >> st;
111         for(int i=0; i<n; i++)
112             mp[st.substr(i,1)]=i;
113         for(int i=0; i<m; i++)
114         {
115             cin >> c1 >> c2 >> w;
116             v1 = mp[c1];
117             v2 = mp[c2];
118             adj[v1].push_back(node(v2,w));
119             in[v2]++;
120         }
121         printf("%d\n", CriticalPath());
122     }
123 
124     return 0;
125 }

 

转载于:https://www.cnblogs.com/blue-lin/p/11041233.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值