题意:n个点m条边的有向图,从所有入度为0的点出发到达n,问所有可能路径中,经过的某条路的最大次数是多少。边全是由标号小的到标号大的。
题解:正向走一遍,记录到达某点的路径总数,反向走一遍,记录某点出发到终点的总情况数。枚举每条边,求边对应两点所记录的两个信息之积的最大值。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=5005; 6 typedef long long ll; 7 int head[2][N],nc[2]; 8 ll tot[2][N]; 9 bool flag[N]; 10 struct Edge 11 { 12 int to,next; 13 }edge[2][N*20]; 14 void add(int a,int b,int k) 15 { 16 edge[k][nc[k]].to=b;edge[k][nc[k]].next=head[k][a];head[k][a]=nc[k]++; 17 } 18 int main() 19 { 20 int n,m; 21 while(scanf("%d%d",&n,&m)!=EOF) 22 { 23 memset(head,-1,sizeof(head)); 24 memset(tot,0,sizeof(tot)); 25 memset(flag,false,sizeof(flag)); 26 nc[0]=nc[1]=0; 27 for(int i=0,a,b;i<m;i++) 28 { 29 scanf("%d%d",&a,&b); 30 add(a,b,0); 31 add(b,a,1); 32 flag[b]=true; 33 } 34 ll ans=0; 35 for(int i=1;i<=n;i++) 36 { 37 if(!flag[i]) 38 tot[0][i]=1; 39 for(int j=head[0][i];j!=-1;j=edge[0][j].next) 40 tot[0][edge[0][j].to]+=tot[0][i]; 41 } 42 tot[1][n]=1; 43 for(int i=n;i>=1;i--) 44 { 45 for(int j=head[1][i];j!=-1;j=edge[1][j].next) 46 tot[1][edge[1][j].to]+=tot[1][i]; 47 } 48 for(int i=1;i<=n;i++) 49 for(int j=head[0][i];j!=-1;j=edge[0][j].next) 50 ans=max(ans,tot[0][i]*tot[1][edge[0][j].to]); 51 printf("%lld\n",ans); 52 } 53 return 0; 54 }