题意:n个点m条边的有向图,从所有入度为0的点出发到达n,问所有可能路径中,经过的某条路的最大次数是多少。边全是由标号小的到标号大的。

题解:正向走一遍,记录到达某点的路径总数,反向走一遍,记录某点出发到终点的总情况数。枚举每条边,求边对应两点所记录的两个信息之积的最大值。

View Code
 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 }