lzm

who dare win.
posts - 14, comments - 29, trackbacks - 0, articles - 0

Critical Path 关键路径

Posted on 2009-04-09 23:02 lzmagic 阅读(1874) 评论(0)  编辑 收藏 引用 所属分类: Algorithm
/**
 * CRITICALPATH(简单版) 关键路径 
 * 输入:无环图g。 
 * 输出:(1)各点最早完成时间ec; 
 *       (2)各点最晚完成时间lc; 
 *       (3)关键路径prev。 
 * 结构:图g用邻接矩阵表示
 * 算法:拓扑排序,动态规划(DP) 
 * 复杂度:O(|V|^2) 
 
*/

#include 
<iostream>
#include 
<string>
#include 
<vector>
#include 
<deque>
#include 
<list>
#include 
<stack>
#include 
<queue>
#include 
<iterator>
#include 
<algorithm>
#include 
<numeric>
#include 
<functional>
#include 
<climits>
using namespace std;

int n;                        // n :顶点个数 
vector<vector<int> > g;        // g :图(graph)(用邻接矩阵(adjacent matrix)表示) 

vector
<int> seq;            // seq :拓扑序列(sequence) 

bool TopSort()        // 拓扑排序 
{
    vector
<int> inc(n, 0);     
    
for (int i = 0; i < n; ++i)
        
for (int j = 0; j < n; ++j)
             
if (g[i][j] < INT_MAX) ++inc[j]; // 计算每个顶点的入度, 
    queue<int> que;
    
for (int j = 0; j < n; ++j)
        
if (inc[j] == 0) que.push(j); // 如果顶点的入度为0,入队。
    int seqc = 0;
    seq.resize(n);
    
while (!que.empty())     // 如果队列que非空,
    {
        
int v = que.front(); que.pop();     
        seq[seqc
++= v;      // 顶点v出队,放入seq中,
        for (int w = 0; w < n; ++w)     // 遍历所有v指向的顶点w,
            if (g[v][w] < INT_MAX)
                
if (--inc[w] == 0) que.push(w); // 调整w的入度,如果w的入度为0,入队。 
    }

    
return seqc == n; // 如果seq已处理顶点数为n,存在拓扑排序,否则存在回路。
}


vector
<int> ec;                // ec : 最早完成时间(early complete time) 
vector<int> lc;                // lc : 最晚完成时间(late complete time) 
vector<int> cp;                // cp : 关键路径(critical path)

void CriticalPath()    // 关键路径 
{
    
// 最早完成时间:ec[0] = 0;
    
//               ec[v] = max(ec[u] + g[u][v])。 
    ec.assign(n, INT_MIN);  ec[seq[0]] = 0;
    
for (int i = 0; i < n - 1++i)
        
for (int v = 0; v < n; ++v)
            
if (g[seq[i]][v] < INT_MAX)
                ec[v] 
= max(ec[v], ec[seq[i]] + g[seq[i]][v]);
    
// 最晚完成时间:lc[n - 1] = ec[n - 1];
    
//               lc[u] = min(lc[v] - g[u][v])。 
    lc.assign(n, INT_MAX);    lc[seq[n - 1]] = ec[seq[n - 1]]; 
    
for (int j = n - 1; j > 0--j)
        
for (int u = 0; u < n; ++u)
            
if (g[u][seq[j]] < INT_MAX)
                lc[u] 
= min(lc[u], lc[seq[j]] - g[u][seq[j]]);
    
// 关键路径:cp[0] = seq[0]; 
    
//           if(松弛时间slack(u, v) = lc[v] - ec[u] - g[u][v]为零) 
    
//             { u为关键路径点;如果u为seq[n - 1],结束。} 
    cp.clear(); cp.push_back(seq[0]); 
    
for (int i = 0; i < n - 1++i)
    
{
        
for (int v = 0; v < n; ++v)
            
if (g[cp[i]][v] < INT_MAX)
            
{
                
int slack = lc[v] - ec[cp[i]] - g[cp[i]][v];
                
if (slack == 0{ cp.push_back(v); break; }
            }

        
if (cp.back() == seq[n - 1]) break;
    }

}


int main()
{
    n 
= 9;
    g.assign(n, vector
<int>(n, INT_MAX));
    g[
0][1= 6; g[0][2= 4; g[0][3= 5;
    g[
1][4= 1;
    g[
2][4= 1;
    g[
3][5= 2;
    g[
4][6= 9; g[4][7= 7;
    g[
5][7= 4;
    g[
6][8= 2;
    g[
7][8= 4;         
    
    
if (TopSort())
    
{
         copy(seq.begin(), seq.end(), ostream_iterator
<int>(cout, " ")); cout << endl;
         CriticalPath();
         copy(ec.begin(), ec.end(), ostream_iterator
<int>(cout, " ")); cout << endl;
         copy(lc.begin(), lc.end(), ostream_iterator
<int>(cout, " ")); cout << endl;
         copy(cp.begin(), cp.end(), ostream_iterator
<int>(cout, " ")); cout << endl;
    }

    
else
    
{
         cout 
<< "Circles exist." << endl;
    }

    
    system(
"pause");
    
return 0;
}


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理