题意不再重复,一条边使用的次数等于从起点走过去的方法数乘以走到终点的方法数。所以就一次正推加一次反推就可以了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=5e3+9;
long long dp[maxn],ans[maxn*10];
long long rate[maxn];
int head[maxn],lon;
struct
{
int to,next;
}e[maxn*10];
void edgeini()
{
memset(head,-1,sizeof(head));
lon=0;
}
void edgemake(int from,int to)
{
e[++lon].to=to;
e[lon].next=head[from];
head[from]=lon;
}
int main()
{
int n,m;
while(scanf("%d %d",&n,&m)!=EOF)
{
edgeini();
for(int i=1,from,to;i<=m;i++)
{
scanf("%d %d",&from,&to);
if(from>to) swap(from,to);
edgemake(from,to);
}
memset(dp,0,sizeof(dp));
memset(ans,0,sizeof(ans));
memset(rate,0,sizeof(rate));
rate[n]=1;
for(int i=n-1;i>=1;i--)
{
rate[i]=1;
int tmp=0;
for(int k=head[i];k!=-1;k=e[k].next)
tmp+=rate[e[k].to];
rate[i]*=tmp;
}
for(int i=1;i<n;i++)
{
if(dp[i]==0) dp[i]=1;
for(int k=head[i];k!=-1;k=e[k].next)
{
int u=e[k].to;
dp[u]+=dp[i];
ans[k]=dp[i]*rate[u];
}
}
sort(ans+1,ans+1+m);
printf("%lld\n",ans[m]);
}
return 0;
}