hihoCoder #1175 : 拓扑排序·二

【题目链接】:click here~~

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒。这事在校内BBS上立刻引起了大家的讨论,当然小Hi和小Ho也参与到了其中。从大家各自了解的情况中,小Hi和小Ho整理得到了以下的信息:

  • 校园网主干是由N个节点(编号1..N)组成,这些节点之间有一些单向的网路连接。若存在一条网路连接(u,v)链接了节点u和节点v,则节点u可以向节点v发送信息,但是节点v不能通过该链接向节点u发送信息。
  • 在刚感染病毒时,校园网立刻切断了一些网络链接,恰好使得剩下网络连接不存在环,避免了节点被反复感染。也就是说从节点i扩散出的病毒,一定不会再回到节点i。
  • 当1个病毒感染了节点后,它并不会检查这个节点是否被感染,而是直接将自身的拷贝向所有邻居节点发送,它自身则会留在当前节点。所以一个节点有可能存在多个病毒。
  • 现在已经知道黑客在一开始在K个节点上分别投放了一个病毒。

举个例子,假设切断部分网络连接后学校网络如下图所示,由4个节点和4条链接构成。最开始只有节点1上有病毒。

最开始节点1向节点2和节点3传送了病毒,自身留有1个病毒:

其中一个病毒到达节点2后,向节点3传送了一个病毒。另一个到达节点3的病毒向节点4发送自己的拷贝:

当从节点2传送到节点3的病毒到达之后,该病毒又发送了一份自己的拷贝向节点4。此时节点3上留有2个病毒:

最后每个节点上的病毒为:

小Hi和小Ho根据目前的情况发现一段时间之后,所有的节点病毒数量一定不会再发生变化。那么对于整个网络来说,最后会有多少个病毒呢?

提示:拓扑排序的应用

输入

第1行:3个整数N,M,K,1≤K≤N≤100,000,1≤M≤500,000

第2行:K个整数A[i],A[i]表示黑客在节点A[i]上放了1个病毒。1≤A[i]≤N

第3..M+2行:每行2个整数 u,v,表示存在一条从节点u到节点v的网络链接。数据保证为无环图。1≤u,v≤N

输出

第1行:1个整数,表示最后整个网络的病毒数量 MOD 142857

样例输入
4 4 1
1
1 2
1 3
2 3
3 4
样例输出
6

【思路】:

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

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

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

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const int MOD=142857;
const double eps=1e-8;
const double inf=1e10;
int t,n,k,m,x;
int father[N],V[N],indegree[N];
vector <int >vec[N];
bool topsort()
{
    queue<int >q;
    while(!q.empty()) q.pop();
    for(int i=1; i<=n; i++)
        if(indegree[i]==0) q.push(i);
    int ans=0,sum=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        //sum++;
        ans+=V[u];
        ans%=MOD;
        for(int i=0; i<vec[u].size(); i++)
        {
            int temp=vec[u][i];
            V[temp]+=V[u];
            V[temp]%=MOD;
            if(--indegree[temp]==0) q.push(temp);
        }
    }
    printf("%u\n",ans);
    /*
    if(sum<n) return false;判断拓扑排序
    return true;
    */
}
int main()
{
    int u,v,a;
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        memset(indegree,0,sizeof(indegree));
        for(int i=1;i<=n;i++) if(vec[i].size()) vec[i].clear();
        for(int i=1; i<=k; i++) { scanf("%d",&v); V[v]++;}
        while(m--)
        {
            scanf("%d%d",&v,&u);
            vec[v].push_back(u);
            indegree[u]++;
        }
        /*
        if(topsort()) puts("YES");
        else puts("NO");
        */
        topsort();
    }
    return 0;
}
时间: 2024-10-13 11:18:12

hihoCoder #1175 : 拓扑排序·二的相关文章

hihoCoder - 1175 - 拓扑排序&#183;二 (拓扑排序的应用)

#1175 : 拓扑排序·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当然小Hi和小Ho也参与到了其中.从大家各自了解的情况中,小Hi和小Ho整理得到了以下的信息: 校园网主干是由N个节点(编号1..N)组成,这些节点之间有一些单向的网路连接.若存在一条网路连接(u,v)链接了节点u和节点v,则节点u可以向节点v发送信息,但是节点v不能通过该链接向节点u发送信息.

hihoCoder#1175拓扑排序应用

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当然小Hi和小Ho也参与到了其中.从大家各自了解的情况中,小Hi和小Ho整理得到了以下的信息: 校园网主干是由N个节点(编号1..N)组成,这些节点之间有一些单向的网路连接.若存在一条网路连接(u,v)链接了节点u和节点v,则节点u可以向节点v发送信息,但是节点v不能通过该链接向节点u发送信息. 在刚感染病毒时,校园网立刻切断

hiho一下 第四十八周 拓扑排序&#183;二【拓扑排序的应用 + 静态数组 + 拓扑排序算法的时间优化】

题目1 : 拓扑排序·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho所在学校的校园网被黑客入侵并投放了病毒.这事在校内BBS上立刻引起了大家的讨论,当然小Hi和小Ho也参与到了其中.从大家各自了解的情况中,小Hi和小Ho整理得到了以下的信息: 校园网主干是由N个节点(编号1..N)组成,这些节点之间有一些单向的网路连接.若存在一条网路连接(u,v)链接了节点u和节点v,则节点u可以向节点v发送信息,但是节点v不能通过该链接向节点u发送信息. 在刚

hihoCoder #1174:拓扑排序&amp;#183;一

[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 因为今天上课的老师讲的特别无聊.小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi.你这学期有选什么课么? 小Hi:挺多的,比方XXX1,XXX2还有XXX3.本来想选YYY2的,可是好像没有先选过YYY1.不能选YYY2. 小Ho:先修课程真是个麻烦的东西呢. 小Hi:没错呢. 好多课程都有先修课程.每次选课之前都得先查查有没有先修.教务发布的先修课程记录都是好多年前的.不但有

hihoCoder 1175:拓扑排序二

题目链接: http://hihocoder.com/problemset/problem/1175 题目难度:一星级(简单题) 今天闲来无事,决定刷一道水题.结果发现这道水题居然把我卡了将近一个钟头. 最后终于调通了.总结起来,原因只有一个:不够仔细. 思路不用细说了,就是拓扑排序的简单应用.然而,一些不起眼的细节才是让你掉坑里的真正原因. 猜猜哪儿可能出bug? // A simple problem, but you can't be too careful with it. #inclu

hihoCoder 1174 拓扑排序&#183;一

#1174 : 拓扑排序·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 由于今天上课的老师讲的特别无聊,小Hi和小Ho偷偷地聊了起来. 小Ho:小Hi,你这学期有选什么课么? 小Hi:挺多的,比如XXX1,XXX2还有XXX3.本来想选YYY2的,但是好像没有先选过YYY1,不能选YYY2. 小Ho:先修课程真是个麻烦的东西呢. 小Hi:没错呢.好多课程都有先修课程,每次选课之前都得先查查有没有先修.教务公布的先修课程记录都是好多年前的,不但有重复的信息,好像

hihoCoder hiho一下 第四十八周 题目1 : 拓扑排序&#183;二

题意:给定一个拓扑图,其中部分结点含有1个病毒,每个结点只要收到病毒就会立即往出边所能到达的点传播,病毒数可叠加,求所有结点的病毒数总和. 思路:根据拓扑的特点,每个入度为0的点肯定不会再被传播病毒,而且会将自己的所有病毒向与其相连的结点传播.那么可以从入度味为0的点着手,逐个删除入度为0的结点,在删除的过程中,更新与其相连的结点的病毒数(即将病毒数累加到该结点),到最后所有结点都没了,各个结点所累积的病毒数的和就是答案. 1 #include<bits/stdc++.h> 2 using n

hihoCoder #1174 : 拓扑排序&#183;一 (判断循环图)

G++ 261ms 13MB 题意:给出n门课程的修读所需要的前置课程的关系,按理说应该是个拓扑图,但是因为某些原因导致了混乱,所以有可能不是一个拓扑图.现在的问题是,判断该图是否为一个拓扑图(即无环图). 思路:每次删除全部入度为0的结点,一直删下去肯定是没有任何点存在的,如果不是拓扑图的话就必有环,那么肯定有点的入度永远不为0.若到删到最后没有点存在,那么就是correct的. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const

两道拓扑排序的问题

多久没写东西了啊.... 两道拓扑排序Liv.1的题....方法是一样的~~ <拓扑排序·二> 题目:http://hihocoder.com/contest/hiho81/problem/1 一个电脑网路,单向边,如果存在边u->v,那么u的病毒会感染到v. 要点,不存在环!那么如果u的入度=0的话,那么u中的病毒数不会再变化. 想到拓扑排序.不断删去入度为0的点.每次删去节点u,如果存在u->v,那么病毒数 num[v] += num[u].问题解决. (用queue实现拓扑排