码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2016]食物链

时间:2018-01-21 11:06:32      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:https   tchar   for   family   add   size   return   tps   路径   

原题链接:https://www.luogu.org/problemnew/show/3183

拓扑排序题

题意简述:给出一个有向图,求由图中所有入度为零的点出发,有多少种路径到达出度为零的点(单点不计入)。

拓扑排序,现将所有入度为零的点加到队列中,同时用一个数组f表示能达到这个点的路径条数,很显然,路径的零的点x,f[x]=1

由各个点出发,将每个点的方案数加到它所能到达的点上,完成拓扑排序后,将所有出度为零的点的f值相加,用一个vis来记录是否有边连向这个点,判断是否需要忽略掉即可。

#include<cstdio>
void read(int &y)
{
    y=0;char x=getchar();
    while(x<0||x>9) x=getchar();
    while(x>=0&&x<=9)
    {
        y=y*10+x-0;
        x=getchar();
    }
}
int n,m,cnt,l=1,r;
int d[100005],c[100005],head[100005];
int q[100005],f[100005],vis[100005];
long long sum;
struct edge
{
    int u,v;
}e[200005];
void add(int u,int v)
{
    e[++cnt].u=head[u];
    e[cnt].v=v;
    head[u]=cnt;
}
void top(int x)
{
    for(int i=head[x];i;i=e[i].u)
    {
        int nxt=e[i].v;
        d[nxt]--;
        if(d[nxt]==0) q[++r]=nxt;
        f[nxt]+=f[x];
    }
}
int main()
{
    read(n);read(m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        read(x);read(y);
        c[x]++;d[y]++;
        vis[x]++;vis[y]++;
        add(x,y);
    }
    for(int i=1;i<=n;i++)
    {
        if(d[i]==0)
        {
            q[++r]=i;
            f[i]=1;
        }
    }
    while(l<=r)
    {
        top(q[l]);
        l++;
    }
    for(int i=1;i<=n;i++)
    {
        if(c[i]==0&&vis[i]!=0) sum+=f[i];
    }
    printf("%lld",sum);
    return 0;
}

 

[HAOI2016]食物链

标签:https   tchar   for   family   add   size   return   tps   路径   

原文地址:https://www.cnblogs.com/zeroform/p/8323437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!