求一个有向图中,从所有起点(入度为0)到终点(唯一,出度为0)经过的次数最多的边经过的次数,两次拓扑排序,一次向前求出所有起点到某个点的所有路径总数f[i],一次向后,求出某个点到终点的所有路径总数g[i],则对一条边(u,v),f[u]*g[v]即为边所需要经过的次数。

1 #include<stdio.h> 2 #include<string.h> 3 #define N 1005//数据范围没有题中描述的那么大…… 4 #define M 10005 5 int map[N][N]; 6 int edge[M][2]; 7 int in[N],out[N],f[N],g[N]; 8 int que[N]; 9 void init() 10 { 11 memset(in,0,sizeof(in)); 12 memset(out,0,sizeof(out)); 13 memset(f,0,sizeof(f)); 14 memset(g,0,sizeof(g)); 15 memset(map,0,sizeof(map)); 16 } 17 int main() 18 { 19 int n,m,i,j,fr,r,u,v,max; 20 scanf("%d%d",&n,&m); 21 init(); 22 for(i=0;i<m;i++) 23 { 24 scanf("%d%d",&u,&v); 25 edge[i][0]=u,edge[i][1]=v; 26 map[u][v]++; 27 in[v]++; 28 out[u]++; 29 } 30 fr=r=0; 31 for(i=1;i<=n;i++) 32 { 33 if(in[i]==0) 34 { 35 que[r++]=i; 36 f[i]=1; 37 } 38 } 39 while(fr<r) 40 { 41 u=que[fr++]; 42 for(i=1;i<=n;i++) 43 { 44 if(map[u][i]) 45 { 46 f[i]+=(map[u][i]*f[u]); 47 in[i]-=map[u][i]; 48 if(in[i]==0) 49 que[r++]=i; 50 } 51 } 52 } 53 fr=r=0; 54 que[r++]=n; 55 g[n]=1; 56 while(fr<r) 57 { 58 u=que[fr++]; 59 for(i=1;i<=n;i++) 60 { 61 if(map[i][u]) 62 { 63 g[i]+=(map[i][u]*g[u]); 64 out[i]-=map[i][u]; 65 if(out[i]==0) 66 que[r++]=i; 67 } 68 } 69 } 70 max=0; 71 for(i=1;i<=m;i++) 72 { 73 if(max<f[edge[i][0]]*g[edge[i][1]]) 74 max=f[edge[i][0]]*g[edge[i][1]]; 75 } 76 printf("%d\n",max); 77 return 0; 78 }