数据结构实验之图论十一:AOE网上的关键路径
Time Limit: 2000 ms Memory Limit: 65536 KiB
Submit Statistic
Problem Description
称为无环图(Directed Acyclic Graph),简称DAG图。
AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG。与AOV不同,活动都表示在了边上,如下图所示:
如上所示,共有11项活动(11条边),9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)。
关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间。如上图所示,1 到2 到 5到7到9是关键路径(关键路径不止一条,请输出字典序最小的),权值的和为18。
Input
这里有多组数据,保证不超过10组,保证只有一个源点和汇点。输入一个顶点数n(2<=n<=10000),边数m(1<=m <=50000),接下来m行,输入起点sv,终点ev,权值w(1<=sv,ev<=n,sv != ev,1<=w <=20)。数据保证图连通。
Output
关键路径的权值和,并且从源点输出关键路径上的路径(如果有多条,请输出字典序最小的)。
Sample Input
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
Sample Output
18
1 2
2 5
5 7
7 9
#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);
p.clear() ;
p.push_back(x) ;
int sum = 0 ;
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 ;
int x = ve[from] , y = vl[to] - ans;
if(x == y)
{
if(key > to)
{
key = to ;
data = ans;
}
flag = true;
}
}
if(flag == true)
{
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 ;
}