資料結構實驗之圖論十一:AOE網上的關鍵路徑
阿新 • • 發佈:2019-01-03
/** 演算法分析,先用拓撲排序判斷是否有迴路,然後在算出每個活動的最早開始時間 *** 最晚開始時間然後在算出關鍵路徑***/ #include <bits/stdc++.h> using namespace std; class Edge { public: int from,to, data; Edge(int x=0,int y=0,int z=0) : from(x), to(y), data(z) {} }; class Vertex { public: int id; int ans; /// 節點入度 vector<int >next; }; class Map { private: int n; bool visit[10000+10] ; vector<Edge> E; vector<int> p; /// 存放拓撲排序序列 int ve[10000+10];/// 頂點活動發生的最早發生時間 int vl[10000+10];/// 定點活動發生的最晚時間 public: Vertex G[10000+10]; void Init(int n) { this->n = n; E.clear(); p.clear(); for(int i = 0 ; i<= n; i++) { ve[i] = - 1 ; vl[i] = INT_MAX; visit[i] = false; G[i].ans = 0 ; G[i].next.clear(); G[i].id = i; } } void Add_Edge(int x,int y,int z=0) { E.push_back(Edge(x,y,z)); int len = E.size(); G[x].next.push_back(len - 1 ) ; G[y].ans++; } bool TopSort() { queue<int> L; for(int i = 1; i<=n ; i++) /// 將入度為零的點進棧 { if(G[i].ans == 0) { L.push(G[i].id); } } while(!L.empty()) { int t = L.front(); L.pop(); p.push_back(t); visit[t] = true; int len = G[t].next.size(); for(int i = 0 ; i<len; i++ ) /// 刪邊 { int j =E[G[t].next[i]].to; int data = E[G[t].next[i]].data; if(visit[j] == false) { G[j].ans--; if(G[j].ans == 0) { L.push(j) ; } } } } if(p.size() == n) { return true; } return false; } void BFS(int x,int y)/// 利用BFS求得 每個定點的最早開始時間 以及最晚時間 { ve[x] = 0 ; memset(visit,false, sizeof(visit)) ; queue<int>L; stack<Edge> l;/// 利 棧 儲存邊的相對位置 L.push(x); while(!L.empty()) { int t = L.front() ; L.pop(); if(visit[t]== true) continue; visit[t] = true; int len = G[t].next.size(); for(int i = 0 ; i<len; i++) { l.push(E[G[t].next[i]]) ; int to = E[G[t].next[i]].to; int data = E[G[t].next[i]].data; ve[to] = max(ve[to],ve[t] + data); L.push(to); } } vl[y] = ve[y]; while(!l.empty()) { Edge t = l.top(); l.pop(); int from = t.from; int to = t.to; int data = t.data; vl[from] = min(vl[from],vl[to]-data); } } void CriticalPath(int x,int y) { memset(visit,false,sizeof(visit)) ; BFS(x,y); /// for(int i = 0 ;) /******** 確定最終路線 *****/ p.clear() ; p.push_back(x) ; int sum = 0 ; // for(int i = 1 ;i<= n;i++) // { // printf("ve[%d] == %d\n",i,ve[i]); // } // cout<<endl; // for(int i = 1 ;i<= n;i++) // { // printf("vl[%d] == %d\n",i,vl[i]); // } // printf("關鍵路徑的資料為 : \n"); queue<int > L; L.push(x) ; memset(visit,false,sizeof(visit)) ; while(!L.empty()) { int t = L.front() ; L.pop(); if(visit[t] == true) { continue; } visit[t] = true; int len = G[t].next.size(); int key = INT_MAX; bool flag = false; int data = -1 ; for(int i = 0 ; i<len; i++) { int to = E[G[t].next[i]].to; int ans = E[G[t].next[i]].data; int from = E[G[t].next[i]].from ; //cout<<"from == "<<from<<" , to == "<<to<<" , data == "<<ans<<endl; // cout<<"ve[from] == "<<ve[from]<<" v1[to] == "<<vl[to]<<endl; int x = ve[from] , y = vl[to] - ans; // cout<<"x = "<<x<<" , y == "<<y<<endl; if(x == y) { if(key > to) { key = to ; data = ans; } flag = true; } } if(flag == true) { //cout<<data<<" "; sum += data; L.push(key) ; p.push_back(key) ; t = key; } } cout<<sum<<endl; int len = p.size(); for(int i = 0 ; i<len-1; i++) { cout<<p[i]<<" "<<p[i+1]<<endl; } } }; Map a; bool b[10000+10] = {false}; /// 源點 bool c[10000+10] = {false}; /// 匯點 int main() { int n,m; while(cin>>n>>m) { a.Init(n); memset(b,false,sizeof(b)) ; memset(c,false,sizeof(c)) ; for(int i = 0 ; i<m; i++) { int x,y,z; cin>>x>>y>>z; a.Add_Edge(x,y,z) ; b[x] = true; c[y] = true; } int x, y ; for(int i = 1 ; i<= n; i++) { if(b[i] == false) { y = i; } if(c[i] == false) { x = i; } } a.CriticalPath(x,y); } return 0 ; } /** 10 13 1 2 5 1 3 6 2 4 3 3 4 6 3 5 3 4 5 3 4 6 4 5 7 1 5 8 4 7 9 5 8 9 2 6 10 4 9 10 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 8 9 4 7 9 2 7 10 1 2 3 1 4 6 1 3 2 2 5 4 2 4 2 3 4 1 3 6 3 4 5 1 5 7 3 6 7 4 ****/ /*************************************************** User name: 大鐵棍子醫院銅主任 Result: Accepted Take time: 104ms Take Memory: 2048KB Submit time: 2017-08-23 11:03:37 ****************************************************/