流量控制题解--zhengjun

题目描述

F L Y FLY FLY农场里的奶牛数量越来越多,牧场里通往牛棚的道路越来越拥堵了,为了缓解交通堵塞, F L Y FLY FLY决定找出最拥挤的道路进行处理。
农场可以看成有 N ( 1 ≤ N ≤ 5000 ) N(1 ≤ N ≤ 5000) N(1N5000)个点(从1到 N N N标号), M ( 1 ≤ M ≤ 50000 ) M(1≤M≤50000) M(1M50000)条边的单向图。总牛棚设置在 N N N号点,其他点均为奶牛们所在的放牧点,每一条道路都由编号较小的路口通向编号较大的路口,所以 F L Y FLY FLY不用担心图上会出现环,而且每条道路最终都可以通向牛棚。注意可能有重边。
这张图上存在许许多多通往 N N N的路径, F L Y FLY FLY需要找到最拥挤的那条道路(最拥挤的道路为通过的路径数量最多的道路)。
保证结果不会超过一个有符号的 32 32 32 位整数。

输入

第一行:两个用空格分开的整数: N N N M M M
第二行到第 M M M + 1行:两个用空格分开的整数表示一条道路连接的两个路口的编号

输出

一行:最拥挤的道路上通过的路径数量

样例输入

7 7
1 3
3 4
3 5
4 6
2 3
5 6
6 7

样例输出

4

提示

(最拥挤的道路是(6,7),一共有四条路径:

1→3→4→6→7

1→3→5→6→7

2→3→4→6→7

2→3→5→6→7

拿到这道题,首先想到是直接dfs,找出所有的路径,再求最大值。可这不是正解,我打出来后直接RE,就想其他办法。

思路

一条可以通向总牛棚的路径一定是从一个入度为0的点开始,到 N N N。那么,一条道路,要找出这条道路通过的路径数量,就相当于找从入度为0的点通向它的路径数和它通向总牛棚的路径数,这条道路路径数量就是两者之和。

代码实现

首先,我们要从所有入度为0的点开始,用一个 f f f数组记录入度为0的点通往当前节点的路径数,入度为0的点的路径数为1,然后到了一个点时,找到所有能这个点能够直接通向的点,如果这个点的 f f f数组还没有值,就 d f s dfs dfs这个点,再把这些点的 f f f数组加起来就可以了。

这样,就将每个点从入度为0的点通向它的路径数记录在 f f f数组中。

接着,我们从 N N N号点开始,还是再用一个 f f f数组记录当前点通往 N N N号点的路径数,找前面的做法就可以了。

这样,就将每个点通向 N N N的路径数记录在 f f f数组中了。

代码

#include<bits/stdc++.h>
#define maxm 500039
#define maxn 50039
#define max(x,y) (x>y?x:y)
using namespace std;
inline void read(int &x)
{
	x=0;register int f=1;register char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	x*=f;
}
int n,m,k1,k2,ans;
int x[maxm],y[maxm];
int head1[maxn],head2[maxn],f1[maxn],f2[maxn],r[maxn];
struct zj1{
    int to,nex;
}a1[maxm];
struct zj2{
    int to,nex;
}a2[maxm];
void add(int x,int y)
{
    a1[++k1].to=y;a1[k1].nex=head1[x];head1[x]=k1;
    a2[++k2].to=x;a2[k2].nex=head2[y];head2[y]=k2;
}
void dfs1(int x)//入度为0的点通往当前节点的路径数
{
    if(!head1[x]){f1[x]=1;return;}//入度为0的点
    for(int i=head1[x];i;i=a1[i].nex)
    {
        if(!f1[a1[i].to])dfs1(a1[i].to);//如果这个点的f数组还没有值,就dfs这个点
        f1[x]+=f1[a1[i].to];
    }
}
void dfs2(int x)//当前点通往 N号点的路径数
{
    if(!head2[x]){f2[x]=1;return;}//N号点
    for(int i=head2[x];i;i=a2[i].nex)
    {
        if(!f2[a2[i].to])dfs2(a2[i].to);//如果这个点的f数组还没有值,就dfs这个点
        f2[x]+=f2[a2[i].to];
    }
}
int main()
{
    read(n);read(m);
    for(int i=1;i<=m;i++)
    {
        read(x[i]);read(y[i]);
        add(x[i],y[i]);
    }
    for(int i=1;i<=n;i++)
    if(!f1[i])dfs1(i);//如果入度为0,就dfs这个点
    dfs2(n);//dfs N号点
    ans=-1;
    for(int i=1;i<=m;i++)
    ans=max(ans,f1[x[i]]*f2[y[i]]);//求出答案
    cout<<ans;
    return 0;
}

谢谢大家–zhengjun

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A_zjzj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值