思路:
第一步:把所有的入度为0度结点压入队列中并让earliest=0;
第二步:进行topsort,并把每个弹出队列的元素压入堆栈中,如果能更新每个弹出元素的邻接点的earliest就更新。
第三步:找出所有的earliest = 最短工期的顶点,令它们的latest = earliest。
第四步;利用堆栈反向更新每个顶点的latest。
第五步:计算每条边的灵活时间,如果等于零说明这条边是关键活动,把它输出。
?分别给出邻接表实现和邻接矩阵实现的代码:
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#define INF 65535
#define MAXV 105
using namespace std;
int n,m,indegree[MAXV];
int flex[MAXV][MAXV];
struct ENode
{
int w,weight;
ENode(int _w, int _weight) : w(_w), weight(_weight) {}
};
vector<ENode> Adj[MAXV];
struct GNode
{
int earliest,latest;
}G[MAXV];
void topsort()
{
int v,u, cnt = 0, tlp = -1;
queue<int> q;
stack<int> s;
for(v=1; v<=n; v++)
{
if(indegree[v]==0)
{
q.push(v);
G[v].earliest = 0;
}
}
while(!q.empty())
{
u = q.front(); q.pop(); s.push(u); cnt++;
for(vector<ENode>::iterator it = Adj[u].begin(); it!=Adj[u].end(); it++)
{
indegree[it->w]--;
if((indegree[it->w])==0) q.push(it->w);
if(G[it->w].earliest < G[u].earliest+it->weight)
{
G[it->w].earliest = G[u].earliest+it->weight;
}
}
}
if(cnt != n) { printf("0\n"); return; }
for(v=1; v<=n; v++)
{
if(G[v].earliest > tlp)
tlp = G[v].earliest;
}
printf("%d\n",tlp);
for(v=1; v<=n; v++)
{
if(G[v].earliest == tlp)
{
G[v].latest = tlp;
}
}
while(!s.empty())
{
u = s.top(); s.pop(); //printf("u = s.top() = %d\n",u);
for(vector<ENode>::iterator it = Adj[u].begin(); it!=Adj[u].end(); it++)
{
//printf("G[%d].latest = %d, it->weight = %d, G[%d].latest = %d\n",it->w,G[it->w].latest,it->weight,u,G[u].latest);
if(G[it->w].latest - it->weight < G[u].latest)
{
G[u].latest = G[it->w].latest - it->weight;
//printf("G[%d].latest = %d\n",u,G[u].latest);
}
}
}
for(v=1; v<=n; v++)
{
for(vector<ENode>::iterator it = Adj[v].begin(); it != Adj[v].end(); it++)
{
flex[v][it->w] = G[it->w].latest - G[v].earliest - it->weight;
}
}
for(v=1; v<=n; v++)
{
for(vector<ENode>::iterator it = Adj[v].begin(); it!=Adj[v].end(); it++)
{
//printf("flex[%d][%d] = %d\n",v,it->w,flex[v][it->w]);
if(flex[v][it->w] == 0)
printf("%d->%d\n",v,it->w);
}
}
}
int main()
{
int i,v1,v2,weight,v;
fill(indegree,indegree+MAXV,0);
fill(flex[0],flex[0]+MAXV*MAXV,-1);
scanf("%d%d",&n,&m);
for(v=1; v<=n; v++)
{
G[v].earliest = -1;
G[v].latest = INF;//printf("G[%d].latest = %d\n",v,G[v].latest);
}
//printf("G[5].latest = %d\n",G[5].latest);
for(i=0; i<m; i++)
{
scanf("%d%d%d",&v1,&v2,&weight);
Adj[v1].insert(Adj[v1].begin(),ENode(v2,weight));
indegree[v2]++;
}
topsort();
return 0;
}
#include<cstdio>
#include<queue>
#include<algorithm>
#include<stack>
#define MAXV 105
#define INF 1000000000
using namespace std;
int n,m,indegree[MAXV];
int E[MAXV][MAXV];
int F[MAXV][MAXV];
struct GNode
{
int earliest,latest;
}G[MAXV];
void Topsort()
{
int i,j,u,v,w,cnt=0;
queue<int> q;
stack<int> s;
for(v=1; v<=n; v++)
{
if(indegree[v]==0)
{
q.push(v);
G[v].earliest = 0;
}
}
while(!q.empty())
{
u = q.front(); q.pop();cnt++;s.push(u);
for(w=1; w<=n; w++)
{
if(E[u][w]<INF)
{
indegree[w]--;
if(indegree[w]==0) q.push(w);
if(G[u].earliest+E[u][w]>G[w].earliest)
G[w].earliest = G[u].earliest+E[u][w];
}
}
}
if(cnt!=n)
{
printf("0\n");
return;
}
int wholetime = -1;
for(v=1; v<=n; v++)
{
if(G[v].earliest>wholetime)
{
wholetime = G[v].earliest;
}
}
printf("%d\n",wholetime);
for(v=1; v<=n; v++)
{
if(G[v].earliest==wholetime)
G[v].latest = G[v].earliest;
}
while(!s.empty())
{
v = s.top(); s.pop();
for(u=1; u<=n; u++)
{
if(E[v][u]<INF&&(G[u].latest-E[v][u]<G[v].latest))
{
G[v].latest = G[u].latest-E[v][u];
}
}
}
for(i=1; i<=n; i++)
for(j=n; j>=1; j--)
{
if(E[i][j]<INF)
{
F[i][j] = G[j].latest - G[i].earliest - E[i][j];
if(F[i][j]==0)
printf("%d->%d\n",i,j);
}
}
}
int main()
{
int i,v1,v2,weight,v;
fill(indegree,indegree+MAXV,0);
fill(E[0],E[0]+MAXV*MAXV,INF);
fill(F[0],F[0]+MAXV*MAXV,INF);
scanf("%d%d",&n,&m);
for(i=0; i<m; i++)
{
scanf("%d%d%d",&v1,&v2,&weight);
E[v1][v2] = weight;
indegree[v2]++;
}
for(v=1; v<=n; v++)
{
G[v].earliest = -1;
G[v].latest = INF;
}
Topsort();
return 0;
}