POJ 3272

题意: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 }

你可能感兴趣的:(poj)