晴神机试模拟题选解 1044 关键路径
题目:
给定一个有N个顶点、M条边的有向图,顶点下标为从1到N,每条边都有边权。判断这个有向图是否是有向无环图,如果是的话,请处理K个查询,每个查询为图中的一条边,求这条边的最早发生时间和最晚发生时间。最后再输出图中的所有关键路径。
输入
每个输入文件中一组数据。
第一行为两个整数N、M,表示有向无环图的顶点数和边数(1<=N<=1000, 0<=M<=N*(N-1)),顶点编号为从1到N。
接下来M行,每行为三个正整数u、v、w(1<=u,v<=N,0<w<=20,u!=v),分别表示有向边的起点、终点、边权。数据保证不会有两条起点和终点都相同的边。
然后是一个正整数K(1<=K<=1000),表示查询个数。
接着是K行,每行为两个正整数u、v,分别表示查询边的起点和终点。数据保证查询边一定是图上存在的边。
输出
如果给出的图不是有向无环图,那么在一行里输出NO,后面的查询结果和关键路径均不需要输出;
如果给出的图是有向无环图,那么在一行里输出YES,接着输出下面的内容:
每个查询一行,输出查询边的最早发生时间和最晚发生时间;
之后一行输出一个整数:关键路径上的边权之和;
最后若干行输出所有关键路径,每行表示其中一条,格式为用->连接的顶点编号。注意,如果有两条关键路径a[1]->a[2]->…->a[k]->a[k+1]->…与b[1]->b[2]->…->b[k]->[k+1]->…,满足a[1]==b[1]、a[2]==b[2]、…、a[k]==b[k]、a[k+1]<b[k+1],那么把关键路径a优先输出。数据保证关键路径条数不超过10000条。
Sample Input 1
4 5
1 2 3
1 3 2
1 4 5
2 4 1
3 4 3
2
1 3
2 4
Sample Output 1
YES
0 0
3 4
5
1->3->4
1->4
Sample Input 2
3 3
1 2 3
2 3 1
3 2 2
2
1 2
2 3
Sample Output 2
NO
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1111;
struct node{
int v,w;
};
vector<node> G[maxn];
vector<int> toporder,pre[maxn],path;
int e[maxn][maxn],l[maxn][maxn];
int n,m,ed,st,maxlen=-1,ind[maxn],ve[maxn],vl[maxn],origin[maxn];
bool istoplogical()
{
queue<int> q;
for(int i=1;i<=n;i++) if(ind[i]==0) q.push(i);
while(!q.empty())
{
int now=q.front();
q.pop();
toporder.push_back(now);
for(int i=0;i<G[now].size();i++)
{
int v=G[now][i].v;
ind[v]--;
if(0==ind[v]) q.push(v);
if(ve[now]+G[now][i].w>ve[v]) ve[v]=ve[now]+G[now][i].w;
}
}
if(toporder.size()==n) return true;
else return false;
}
void DFS(int u)
{
if(pre[u].size()==0)
{
path.push_back(u);
for(int i=0;i<path.size();i++)
{
cout<<path[i];
if(i<path.size()-1) cout<<"->";
else cout<<endl;
}
path.pop_back();
}
path.push_back(u);
sort(pre[u].begin(),pre[u].end());
for(int i=0;i<pre[u].size();i++) DFS(pre[u][i]);
path.pop_back();
}
int main()
{
cin>>n>>m;
int u,v,w,k;
for(int i=0;i<m;i++)
{
cin>>u>>v>>w;
ind[v]++;
origin[v]++;
G[u].push_back(node{v,w});
}
if(istoplogical())
{
for(int i=1;i<=n;i++) if(ve[i]>maxlen) maxlen=ve[i];
fill(vl,vl+maxn,maxlen);
while(toporder.size()!=0)
{
int u=toporder[toporder.size()-1];
toporder.pop_back();
for(int i=0;i<G[u].size();i++)
{
v=G[u][i].v;
if(vl[v]-G[u][i].w<vl[u]) vl[u]=vl[v]-G[u][i].w;
}
}
for(int u=1;u<=n;u++)
{
for(int i=0;i<G[u].size();i++)
{
int v=G[u][i].v,w=G[u][i].w;
e[u][v]=ve[u];
l[u][v]=vl[v]-w;
if(e[u][v]==l[u][v]) pre[u].push_back(v);
}
}
printf("YES\n");
cin>>k;
while(k--)
{
cin>>u>>v;
printf("%d %d\n",e[u][v],l[u][v]);
}
printf("%d\n",maxlen);
for(int i=1;i<=n;i++) if(origin[i]==0&&pre[i].size()!=0) DFS(i);
}
else printf("NO\n");
return 0;
}