拓扑排序之五
//poj 3272 Cow Traffic
//求出由入度为0的源点到汇点的所有路径中使用最频繁那条边总共使用的次数
//f[i] 为入度为0的点到结点i的路径条数, g[i]为结点i到N的路径条数
//枚举每个边(s为始点,t为终点),则所有边的f[s]*g[t]的最大值即为答案
#include<iostream> //拓扑排序
#include<deque>
using namespace std;
int n,m,table[5002][5002],side[50002][2];
int f[5002],g[5002],in[5002],out[5002];
deque<int> pre,post;
int main()
{
cin>>n>>m;
for(int i=0;i<m;++i)
{
cin>>side[i][0]>>side[i][1];
in[side[i][1]]++; //有重边,如果用邻接表就不必考虑重边的问题了
out[side[i][0]]++;
table[side[i][0]][side[i][1]]++;
}
for(int i=1;i<=n;++i)
if(in[i]==0) //可能有多个源点
{
pre.push_back(i);
f[i]=1;
}
while(!pre.empty())
{
for(int i=1;i<=n;++i)
if(table[pre.front()][i]>0)
{
f[i]+=table[pre.front()][i]*f[pre.front()]; //重边不能忽略掉,有m次重边就是m条路径数
in[i]-=table[pre.front()][i];
if(in[i]==0)
pre.push_back(i);
}
pre.pop_front();
}
post.push_back(n); //汇点唯一:the barn is at intersection number N
g[n]=1;
while(!post.empty())
{
for(int i=1;i<=n;++i)
if(table[i][post.front()]>0)
{
g[i]+=table[i][post.front()]*g[post.front()];
out[i]-=table[i][post.front()];
if(out[i]==0)
post.push_back(i);
}
post.pop_front();
}
int s=0;
for(int i=0;i<m;++i)
s=max(s,f[side[i][0]]*g[side[i][1]]);
cout<<s<<endl;
return 0;
}