zoukankan      html  css  js  c++  java
  • Little W and Contest HDU

    Parctice link: https://vjudge.net/problem/HDU-6795

    Problem Description

    There are n members in our ACM club. Little W wants to select three persons from our club to form a new team taking part in provincial ACM contests, as it is known by all of us that any ACM contest requires a normal team to have three members.
    Little W has divided our club members into two role groups. The first group contains only readers who dedicate themselves to reading problems during contests, though sometimes they may also prepare drinking and food for the team. For the sake of measurement, we define the power of a reader as 1. The second part contains only coders who code and test programs all the time, and similarly, we define the power of a coder as 2.

    Little W thinks it will be a tremendous disaster when a team has two readers because in that case, the total power of this team is less than 5 and thus it has a high risk to fail the contest. To avoid that, Little W thinks a new team must have at least two coders.

    Additionally, Little W defines the relationship between club members with transitivity. That is, for every three members AB, and C, if A is familiar with B, and B is familiar with C, then A will be familiar with C through B instantly. Based on the definition, it is forbidden for the team to have any two members familiar with each other.

    At first, no member of our club is familiar with any other, and then Little W will repeatedly make an introduction between two members who are currently strangers to each other until each member is familiar with all the others. During this process, there will be exactly (n1) introductions.

    Now, for i=1,2,,n, Little W wants you to count the combinations of three club members that can form a new team after the first (i1) introductions have been made. However, the numbers of combinations may be quite gigantic, so you just need to report each number in modulo (109+7).

     Input

    There are several test cases.

    The first line contains an integer T (1T10), denoting the number of test cases. Then follow all the test cases.

    For each test case, the first line contains an integer n (1n105), denoting the number of members in this club.

    The second line contains n integers consisting of only 1 and 2, where the i-th integer represents the power of the i-th member.

    The next (n1) lines describe all introductions in chronological order of occurrence, where each line contains two integers u and v (1u,vn,uv), representing an introduction between the u-th member and the v-th member, who are currently strangers to each other.

    It is guaranteed that the sum of n is no larger than 106.

     Output

    For each test case, output n lines, where the i-th line contains an integer, denoting the number of combinations of three club members, in modulo (109+7), that can form a new team after the first (i1) introductions have been made.
     

    题意:给你 n 个人,这 n 个人有 1 或者 2 的权值,再给你分别给你 n - 1条边,你需要在这 n 个人中挑选 3 个人,且这三个人的权值总和大于等于5,并且这三个人在图上是不连通的,问你每添加一条边,可以挑选的总方案数分别是多少。

    思路:首先,考虑没有边时,我们假设 cnt1 是拥有权值为 1 的人的数量,cnt2 是拥有权值 2 的人的数量,那么初始方案就是

    ans=C(2,cnt2)*C(1,cnt1)+C(3,cnt2)

               接下来就要考虑有边的情况,首先 设 p1[ i ] 是以 i 为根节点的连通块的 1 的权值的人的数量, p2[ i ]就是以 i 为根节点的连通块的 2 的权值的人的数量。然后引入一条边(u,v)时,设三个集合 G( u )即以u为根节点的连通块,G( v )时以 v 为根节点的连通块,G( r )是其他连通块,那么引入这条边后,就有一些方案不能成立,就是三个人分别属于G( u)、G( v )和G( r )的情况。也就是(2、2、1)、(2、2、2)、(1、2、2)和(2、1、2)四种情况,依次减去这四种情况,就是在添加这条边后的方案数,最后用并查集合并两个点所在的连通块。

    代码:

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define INF 0x3f3f3f3f
     4 #define mem(a,x) memset(a,x,sizeof(a))  
     5 #define _for(i,a,b) for(int i=a; i< b; i++)
     6 #define _rep(i,a,b) for(int i=a; i<=b; i++)
     7 #define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
     8 using namespace std;
     9 const int MOD = 1e9+7 ;
    10 const int maxn = 100005 ;
    11 
    12 int fa[maxn];
    13 int p1[maxn],p2[maxn];   //以i为根的连通块含1 和含2 
    14 int a[maxn];
    15 int n;
    16 ll ans=0;
    17 int find(int x)
    18 {
    19   return (fa[x]==x)?x:(fa[x]=find(fa[x]));
    20 }
    21 
    22 int main()
    23 {
    24     int T;
    25     scanf("%d",&T);
    26     while(T--){
    27       ll x=0,y=0;
    28       ans=0;
    29       scanf("%d",&n);
    30       for(int i=1;i<=n;i++){
    31         scanf("%d",&a[i]);
    32         if(a[i]==1){
    33           x++;
    34           p1[i]=1;
    35           p2[i]=0;
    36         }
    37         if(a[i]==2){
    38           y++;
    39           p1[i]=0;
    40           p2[i]=1;
    41         }
    42         fa[i]=i;
    43       }
    44       ans=(ll)(y*(y-1)/2)*x+(ll)(y*(y-1)*(y-2))/6;
    45       ans=ans%MOD;
    46       printf("%lld
    ",ans);
    47       for(int i=1;i<n;i++){
    48           int u,v;
    49           ll k=0;
    50           scanf("%d %d",&u,&v);
    51           int pu=find(u),pv=find(v);
    52           k=(k+(ll)(p2[pu]*p2[pv])*(y-p2[pu]-p2[pv]))%MOD;
    53           k=(k+(ll)(p2[pu]*p1[pv])*(y-p2[pu]-p2[pv]))%MOD;
    54           k=(k+(ll)(p1[pu]*p2[pv])*(y-p2[pu]-p2[pv]))%MOD;
    55           k=(k+(ll)(p2[pu]*p2[pv])*(x-p1[pu]-p1[pv]))%MOD;
    56           ans=(ans-k+MOD)%MOD;
    57           printf("%lld
    ",ans);
    58           fa[pv]=pu;
    59           p1[pu]+=p1[pv];
    60           p2[pu]+=p2[pv];
    61       }
    62 
    63     }
    64     return 0;
    65 }
    View Code
    越自律,越自由
  • 相关阅读:
    oracle之check约束小结
    非归档模式下使用Rman进行备份和恢复
    R中,定义一个长度为0的向量
    R中,去掉dataframe中的NA行
    Oracle数据库的后备和恢复————关于检查点的一些知识
    关于oracle修复控制文件与数据文件不一致的问题----
    《SLAM机器人基础教程》第三章 单片机与STM32:GPIO实验及Keil软件使用WatchWindows进行Debug调试
    《SLAM导航机器人基础》第三章:单片机与STM32:单片机概述和Keil开发环境配置
    《SLAM导航机器人基础》第二章:C/C++编程(后)
    《SLAM导航机器人基础》第二章:C/C++编程(中)
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/13485500.html
Copyright © 2011-2022 走看看