日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

All men are brothers(并查集+思维 好题!!!)

發布時間:2023/12/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 All men are brothers(并查集+思维 好题!!!) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈接:https://ac.nowcoder.com/acm/contest/889/E
來源:牛客網

Amy asks Mr. B problem E. Please help Mr. B to solve the following problem.

There are n people, who don’t know each other at the beginning.
There are m turns. In each turn, 2 of them will make friends with each other.
The friend relation is mutual and transitive.
If A is a friend of B, then B is also a friend of A.
For example, if A is a friend of B, B is a friend of C, then A and C are friends.
At the beginning and after each turn, please calculate the number of ways to select four people from, such that any two of these four are not friends.

輸入描述:
The first line contains two integers, n and m (n <= 100000, m <= 200000), which are the number of people, and the number of turns.

In the following m lines, the i-th line contains two integers x and y ( 1 <= x <= n, 1 <= y <= n, x ≠ y), which means the x-th person and the y-th person make friends in the i-th turn.

The x-th person and y-th person might make friends in several turns.
輸出描述:
Output m+1 lines, each line contains an integer, which is the number of quadruples.

Output at the beginning and after each turn, so there are m+1 lines.
示例1
輸入
復制
6 6
1 2
3 4
4 5
3 5
3 6
2 4
輸出
復制
15
9
4
0
0
0
0
示例2
輸入
復制
100000 0
輸出
復制
4166416671249975000
說明
Don’t use int.

官方題解如上。
這個題目解法不少,并查集+dp或者像題解這么做。個人認為題解這樣算是比較好理解的。dp確實很簡單,但是真的不好理解(dp算是一點不會吧)。
一開始我們能求出原始總共有多少種做法。合并兩個集合之后,對原答案的貢獻是多少?這是解題應該想的。
假設是第一次合并,合并兩個集合之前,我們選四個人,可以直接c(n,4)來求解。
合并之后,減少了多少呢?在合并之前,我們可以在要合并的兩個集合中各選出一個人,在從剩余的里面選出兩個人,在剩余的里面選出兩個人還需要減去在相同集合選出兩個人的情況。這是這兩個集合在合并前做的貢獻,合并后就沒有了。。那么我們在合并后就應該減去這一塊值。這就是合并后的答案值。在剩余的人里面選出兩個人,我們要減去相同集合里面選出兩個人的情況,我們設一個變量sum記錄一下,在一開始這個值為0,合并某兩個集合后,對于sum來說,少了(size[t1](size[t1]-1)/2+(size[t2](size[t2]-1)/2))種情況(就是在這兩個集合選出兩個人的情況),但是多了這兩個集合合并起來之后選出兩個人的情況。這樣想就很簡單了。
代碼如下:

#include<bits/stdc++.h> #define ll long long using namespace std;const int maxx=1e5+100; int f[maxx]; ll size[maxx]; ll ans,sum; ll n,m,k;int getf(int u) {return u==f[u]?u:f[u]=getf(f[u]); } void merge(int u,int v) {int t1=getf(u);int t2=getf(v);if(t1!=t2){ll sub=size[t1]+size[t2];//要合并的兩個集合總數 sum-=(size[t1]*(size[t1]-1)/2+size[t2]*(size[t2]-1)/2);// 合并后對于sum減少了這些ll lose=size[t1]*size[t2]*((n-sub)*(n-sub-1)/2-sum);//合并兩個集合對總數的貢獻是減少了要合并的兩個集合乘積再乘上剩下的人里面選出2個人 ans-=lose;sum+=sub*(sub-1)/2;//合并之后對sum增加了這些k--;//合并一次,集合數就減少一個,少于四個就直接輸出零就行。f[t1]=t2;size[t2]+=size[t1];}printf("%lld\n",ans); } int main() {int x,y;while(~scanf("%lld%lld",&n,&m)){for(int i=0;i<=n;i++) f[i]=i,size[i]=1;k=n;sum=ans=0;ans=n*(n-1)/2;ans*=(n-2);ans/=12;ans*=(n-3);printf("%lld\n",ans);while(m--){scanf("%d%d",&x,&y);if(k<4) printf("0\n");else merge(x,y);}}return 0; }

努力加油a啊,(o)/~

總結

以上是生活随笔為你收集整理的All men are brothers(并查集+思维 好题!!!)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。