1638: [Usaco2007 Mar]Cow Traffic 奶牛交通

来源:互联网 发布:淘宝买家秀福利地址 编辑:程序博客网 时间:2024/05/29 11:43

题目链接

题目大意:n个点,m条有向边,从每个入度为0的点走到编号为n的点,求经过次数最多的边的经过次数

题解:把边拆成两点,由乘法原理
一条边(a,b)的经过次数=起点到a的路径条数*b到编号为n的路径条数

建正反图后dp就行

我的收获:点/边的转化,数学(

#include <iostream>#include <cstdio>#include <cmath>#include <cstring>using namespace std;const int M=50005;int n,m,t,ans;int head[M],ui[M],vi[M];int f[M],g[M];struct edge{int to,nex;}e[M*2];void add(int u,int v){e[t]=(edge){v,head[u]};head[u]=t++;}void dp1(int x){    if(head[x]==-1){f[x]=1;return;}    for(int i=head[x];i!=-1;i=e[i].nex)    {        if(!f[e[i].to]) dp1(e[i].to);        f[x]+=f[e[i].to];    }}void dp2(int x){    if(head[x]==-1){g[x]=1;return;}    for(int i=head[x];i!=-1;i=e[i].nex)    {        if(!g[e[i].to]) dp2(e[i].to);        g[x]+=g[e[i].to];    }}void work(){    for(int i=1;i<=n;i++) if(!f[i]) dp1(i);    t=0;memset(head,-1,sizeof(head));    for(int i=1;i<=m;i++) add(vi[i],ui[i]);    dp2(n);    for(int i=1;i<=m;i++) ans=max(ans,g[ui[i]]*f[vi[i]]);    printf("%d\n",ans);}void init(){    t=0;memset(head,-1,sizeof(head));    cin>>n>>m;    for(int i=1;i<=m;i++)        scanf("%d%d",&ui[i],&vi[i]),add(ui[i],vi[i]);}int main(){    init();     work();    return 0;}
阅读全文
0 0