关键路径 SDUTOJ 2498
SDUTOJ 2498 AOE网上的关键路径
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图。
AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG。与AOV不同,活动都表示在了边上,如下图所示:
如上所示,共有11项活动(11条边),9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)。
关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间。如上图所示,1
到2 到 5到7到9是关键路径(关键路径不止一条,请输出字典序最小的),权值的和为18。
输入
这里有多组数据,保证不超过10组,保证只有一个源点和汇点。输入一个顶点数n(2<=n<=10000),边数m(1<=m
<=50000),接下来m行,输入起点sv,终点ev,权值w(1<=sv,ev<=n,sv != ev,1<=w
<=20)。数据保证图连通。
输出
关键路径的权值和,并且从源点输出关键路径上的路径(如果有多条,请输出字典序最小的)。
示例输入
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
示例输出
18 1 2 2 5 5 7 7 9
1 /*以后记住,输出路径的字典序最小,要反存边,才可以取到字典序*/ 2 /*这个题目的精华就在把边反向存,而不是正向存,我们可以这样解释一下:路径的字典序最小就是我们走到一个点的时候,向下一步走时,选择编号最小的,这就是字典序,但是最短路的更新过程中,(dis[edge[l].v]==dis[x]+edge[l].w&&x<pre[edge[l].v],明显是对该点之前的点的编号取小,这样取出来,会有可能不是字典序 3 */ 4 #include<queue> 5 #define N 10010 6 #include<iostream> 7 #define M 50010 8 using namespace std; 9 #include<cstdio> 10 #include<cstring> 11 struct Edge{ 12 int v,last,w; 13 }edge[M]; 14 int head[N],ans[N],pre[N],n,m,dis[N],indu[N],chudu[N]; 15 bool inque[N]; 16 void add_edge(int u,int v,int w,int k) 17 { 18 edge[k].v=v;edge[k].w=w; 19 edge[k].last=head[u]; 20 head[u]=k; 21 } 22 void input() 23 { 24 int u,v,w; 25 for(int i=1;i<=m;++i) 26 { 27 scanf("%d%d%d",&u,&v,&w); 28 add_edge(v,u,w,i); 29 indu[u]++;chudu[v]++; 30 } 31 } 32 void spfa(int u,int v) 33 { 34 queue<int>que; 35 que.push(u); 36 pre[u]=0;dis[u]=0; 37 inque[u]=true; 38 while(!que.empty()) 39 { 40 int x=que.front(); 41 que.pop(); 42 inque[x]=false; 43 for(int l=head[x];l;l=edge[l].last) 44 { 45 if(dis[edge[l].v]<dis[x]+edge[l].w||(dis[edge[l].v]==dis[x]+edge[l].w&&x<pre[edge[l].v])) 46 { 47 dis[edge[l].v]=dis[x]+edge[l].w; 48 pre[edge[l].v]=x; 49 if(!inque[edge[l].v]) 50 { 51 inque[edge[l].v]=true; 52 que.push(edge[l].v); 53 } 54 } 55 } 56 } 57 } 58 void print(int u,int v) 59 { 60 printf("%d\n",dis[v]); 61 int t=v; 62 ans[++ans[0]]=v; 63 while(pre[t]!=0) 64 { 65 ans[++ans[0]]=pre[t]; 66 t=pre[t]; 67 } 68 for(int i=2;i<=ans[0];++i) 69 printf("%d %d\n",ans[i-1],ans[i]); 70 } 71 int main() 72 { 73 while(scanf("%d%d",&n,&m)==2) 74 { 75 memset(dis,0,sizeof(dis)); 76 memset(edge,0,sizeof(edge)); 77 memset(head,0,sizeof(head)); 78 memset(indu,0,sizeof(indu)); 79 memset(chudu,0,sizeof(chudu)); 80 memset(pre,127,sizeof(pre)); 81 memset(ans,0,sizeof(ans)); 82 memset(inque,false,sizeof(inque)); 83 input(); 84 int u,v; 85 for(int i=1;i<=n;++i) 86 { 87 if(!indu[i]) u=i; 88 if(!chudu[i]) v=i; 89 } 90 spfa(u,v); 91 print(u,v); 92 } 93 return 0; 94 }