hihocoder 1175 拓扑排序二

[hihocoder](http://hihocoder.com/problemset/problem/1175)

对于一个节点i来说,如果我们能够先计算出它所有前驱节点的病毒数量,就可以直接推算出它最后的病毒数量了,但是怎么来计算所有前驱节点呢?

这就要从图的性质入手了。我们现在的网络是没有环的,对于任意一个节点i,当它将自己所有的病毒都传送出去之后,它自身的病毒数量就不会改变了。那么我们不妨从没有前驱节点,也就是入度为0的节点开始考虑。

对于这些节点,它并不会再增加病毒数量。那么我们就根据它所关联的连接将病毒分发出去,然后这个节点就没有作用了。那不妨就删掉好了,它所关联的边也删掉,这样图中又会产生一些新的没有入度的节点。这样一直删点,直到所有的点都被删掉,将所有点的病毒数量加起来就是总的病毒数。

#include <bits/stdc++.h>

using namespace std;

const int maxn = 1e5 + 10;
const int mod = 142857;
int t,n,m,k,x,u,v,num;
vector<int> G[maxn];
int inDeg[maxn];
int virus[maxn];
queue<int> q;

void topSort()
{
    while(!q.empty()) q.pop();
    for(int i=1;i<=n;i++) if(!inDeg[i]) q.push(i);
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
        for(int i=0;i<G[now].size();i++)
        {
            int nxt = G[now][i];
            if(--inDeg[nxt] == 0) q.push(nxt);
            virus[nxt]=(virus[nxt]+virus[now])%mod;
        }
    }
}

int main()
{
    while(~scanf("%d%d%d",&n,&m,&k))
    {
        int ans;
        memset(inDeg,0,sizeof(inDeg));
        memset(virus,0,sizeof(virus));
        for(int i=1;i<=n;i++) G[i].clear();
        while(k--)
        {
            scanf("%d",&x);
            virus[x]++;
        }
        while(m--)
        {
            scanf("%d%d",&u,&v);
            G[u].push_back(v);
            inDeg[v]++;
        }
        topSort();
        ans=0;
        for(int i=1;i<=n;i++) ans=(ans+virus[i])%mod;
        printf("%d
",ans);
    }
}

原文地址:https://www.cnblogs.com/Roni-i/p/9175698.html