hihoCoder hiho一下 第四十八周 题目1 : 拓扑排序·二

 

 

题意:给定一个拓扑图,其中部分结点含有1个病毒,每个结点只要收到病毒就会立即往出边所能到达的点传播,病毒数可叠加,求所有结点的病毒数总和。

思路:根据拓扑的特点,每个入度为0的点肯定不会再被传播病毒,而且会将自己的所有病毒向与其相连的结点传播。那么可以从入度味为0的点着手,逐个删除入度为0的结点,在删除的过程中,更新与其相连的结点的病毒数(即将病毒数累加到该结点),到最后所有结点都没了,各个结点所累积的病毒数的和就是答案。

 

 1 #include<bits/stdc++.h>

 2 using namespace std;

 3 const int N=100100;

 4 const int mod=142857;

 5 

 6 bool init[N];   //初始是否有病毒

 7 int cnt[N];     //各点的入度

 8 vector< vector<int> >   vect;   //邻接表

 9 int ans[N]; //各个节点的病毒数,不包括其自身初始的那个病毒

10 

11 

12 int cal(int n, int k)

13 {

14     vector<int> a;

15     for(int i=1; i<=n; i++)    if(!cnt[i]) a.push_back(i);  //先装进去初始时入度为0的点

16 

17     vector<int> b;

18     while(!a.empty())

19     {

20         b.clear();

21         for(int i=0; i<a.size(); i++)   //对于每个入度为0的点,更新与其相连的每个点的病毒数

22         {

23             for(int j=0; j<vect[a[i]].size(); j++)

24             {

25                 int tmp=vect[a[i]][j];

26                 cnt[tmp]--; //入度减少1

27                 ans[tmp]=(ans[tmp]+ans[a[i]]+init[a[i]])%mod;   //更新病毒数,包括初始那个病毒

28                 if(!cnt[tmp])    b.push_back(tmp);  //又一个入度为0的

29             }

30         }

31         a.clear();

32         if(!b.empty())

33             a.insert(a.end(), b.begin(), b.end());

34     }

35     int sum=0;

36     for(int i=1; i<=n; i++) //统计

37         sum=(sum+ans[i])%mod;

38     sum+=k; //还有初始的病毒

39     return sum%mod;

40 }

41 

42 

43 int main()

44 {

45     //freopen("e://input.txt","r",stdin);

46     int k, n, m, a, b;

47     cin>>n>>m>>k;

48     vector<int> tmp;

49     for(int i=0; i<=n; i++)    vect.push_back(tmp); //初始化

50 

51     for(int i=0; i<k; i++)  //k个病毒

52     {

53         scanf("%d",&a);

54         init[a]=true;

55     }

56     for(int i=0; i<m; i++)  //m个边

57     {

58         scanf("%d%d",&a,&b);

59         vect[a].push_back(b);

60         cnt[b]++;   //入度数

61     }

62     printf("%d\n",cal(n,k));

63     return 0;

64 }
AC代码

 

你可能感兴趣的:(code)