QZEZOJ 流量控制题解--zhengjun

题目描述

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

输入

第一行:两个用空格分开的整数:\(N\)\(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\)。那么,一条道路,要找出这条道路通过的路径数量,就相当于找从入度为0的点通向它的路径数和它通向总牛棚的路径数,这条道路路径数量就是两者之和。

代码实现

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

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

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

这样,就将每个点通向\(N\)的路径数记录在\(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

posted @ 2022-06-10 18:14  A_zjzj  阅读(27)  评论(0编辑  收藏  举报