• Codeforce Round #548(Div2)


      D:(求联通分量个数)

      题意:有两个数n,k,分别代表树的节点个数和一个点集的点的数量

      给你一棵树,树的边有黑色的有红色的,定义满足要求的点集为:这个点集有k个点,并且点集中一个点到达其余点的路径中,必须有一条边是黑色的,求满足要求的点集的数量

      分析:

      emmm其实第一眼看到这个题是没有思路的,但是后来发现,点集总数量为n^k(从n个点中抽取k次),我们可以用 base=n^k减去不满足条件的点集数量就ok

      然后我们来分析一下什么样的点集是不满足条件的:

      已知满足条件的点集是路径上至少有一条黑色边的,所以不满足条件的点集是:点集中任意两点的最短路径的边都是红色的,因此,不满足条件的点集所在的联通分量的边都是红色的,所以不满足的点集的个数就是:

      定义每个联通分量大小为Pi,数量为  sun(Pi^k)

      所以我们只要移除黑色边,求红色边构成图的联通分量的个数以及大小就OK

      代码如下:

      

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int maxn=1e5+5;
     5 const int mod=1e9+7;
     6 bool vis[maxn];
     7 vector<int>G[maxn];
     8 int n,k;
     9 int dfs(int v)
    10 {
    11     vis[v]=1;
    12     int t=1;
    13     for(int i=0;i<G[v].size();++i)
    14     {
    15         int to=G[v][i];
    16         if(vis[to]) continue;
    17         t+=dfs(to);
    18     }
    19     return t;
    20 }
    21 ll pow(ll base)
    22 {
    23     int t=base;
    24     for(int i=1;i<k;++i)
    25     {
    26         base*=t;
    27         base%=mod;
    28     }
    29     return base;
    30 }
    31 int main()
    32 {
    33     cin>>n>>k;
    34     for(int i=1;i<n;++i) 
    35     {
    36         int a,b,c;
    37         cin>>a>>b>>c;
    38         if(c==0) G[a].push_back(b),G[b].push_back(a); 
    39     }
    40     int base=pow(n);
    41     int sub=0;
    42     for(int i=1;i<=n;++i)
    43     {
    44         if(vis[i]==0) sub+=pow(dfs(i));
    45         sub%=mod;
    46     }
    47     printf("%d",base-sub>=0?base-sub:base-sub+mod);
    48 }
  • 相关阅读:
    day003|python基础回顾3
    14Linux之网络管理
    13Linux之磁盘管理
    12Linux之进程管理
    11Linux之软件包管理
    10Linux之用户权限管理
    09Linux之文件管理
    08Linux之目录结构
    07Linux之bash解释器交互式环境特性
    06Linux之shell介绍
  • 原文地址:https://www.cnblogs.com/codeoosacm/p/10682841.html
Copyright © 2020-2023  润新知