2020HDU多校第三場 1005 Little W and Contest

chuliyou發表於2020-07-28

Little W and Contest

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


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.
 

 

Sample Input
1
5
2 2 2 1 1
4 5
1 4
2 1
3 2
 

 

Sample Output
7
7
3
0
0
題意:
ACM俱樂部有n名成員,每個成員可以擔當讀題或者編碼的任務,讀題用1表示,編碼用2表示,一個隊伍有三名成員,其中至少有兩名編碼選手,剛開始大家互不熟悉,每過一天就會有兩個人變得相互熟悉,且雙方會熟悉對方所熟悉的人,大概就是朋友的朋友就是我的朋友的意思,問從大家都不熟悉開始,到接下來n-1天,每一天能組隊的方案數,輸出mod 1e9+7後的結果。
思路:
考慮並查集,fat表示該成員所屬的集合,s1表示該集合內讀題選手的總人數,s2表示該集合內編碼選手的總人數,每次找到兩名在今天熟悉的選手的各自所屬集合,考慮兩名選手的身份減去相應的方案數,然後將兩名選手所屬的集合合併。
#include<bits/stdc++.h>

#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repp(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define perr(i,a,b) for(int i=a;i>b;i--)
#define pb push_back
#define eb push_back
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=1e9+7;
ll max_3(ll a,ll b,ll c){if(a>b&&a>c)return a;if(b>c)return b;return c;}
ll min_3(ll a,ll b,ll c){if(a<b&&a<c)return a;if(b<c)return b;return c;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qmul(ll a,ll b){ll s=(long double)a/mod*b;s=a*b-s*mod;if(s<0)s+=mod;if(s>=mod)s-=mod;return s;}


template <typename _Tp> inline _Tp read(_Tp&x){
    char c11=getchar(),ob=0;x=0;
    while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
    while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}





const int maxn=1e5+7;
int fat[maxn],s1[maxn],s2[maxn],a[maxn]; 
ll cnt1,cnt2;


int find(int x){return fat[x]==x?x:find(fat[x]);}
int main()
{
    multiCase
    {
        cnt1=cnt2=0;
        int n;
        read(n);
        rep(i,1,n)
        {
            read(a[i]);
            if(a[i]==1)s1[i]=1,s2[i]=0,cnt1++;
            else s2[i]=1,s1[i]=0,cnt2++;
            fat[i]=i;
        }
        ll ans=cnt2*(cnt2-1)*(cnt2-2)/6+cnt2*(cnt2-1)*cnt1/2;
        printf("%lld\n",ans%mod);
        repp(j,1,n)
        {
            int u,v;
            read(u);read(v);
            u=find(u);v=find(v);//找到u和v所屬的集合 
            ans-=s2[u]*s2[v]*(cnt2-s2[u]-s2[v]);//這兩個人都是2,所選為“2、2、2 ”的情況 
            ans-=s2[u]*s2[v]*(cnt1-s1[u]-s1[v]);//這兩個人都是2,所選為“2、2、1 ”的情況 
            ans-=s1[u]*s2[v]*(cnt2-s2[u]-s2[v]);//兩個人分別是1、2,所選為“1、2、2 ”的情況 
            ans-=s2[u]*s1[v]*(cnt2-s2[u]-s2[v]); //兩個人分別是2、1,所選為“2、1、2 ”的情況 
            fat[u]=v;//將這兩個人所處的集合合併 ,兩集合中含1和含2的總人數也要合併 
            s1[v]+=s1[u]; 
            s2[v]+=s2[u];
            printf("%lld\n",ans%mod);
        }
    }
    
    return 0;
}

 

相關文章