题意:有若干个点,若干个点之间有直线相连,问全部的点中,有多少三个点之间相互没有直接连接的方案。
分析:这道题很容易想到(怎么可能orz)用bitset求交集,然后用容斥,补这道题的时候容斥部分看了好久,果然我数学还是太菜了。先求出所有可能的排列组合all = C(n,3); 对于容斥,one是那些连有一条边的两个点,m*C(n-2(除去连着的两点再选一点),1); two是那些一个点可以连哪两个点的排列组合,设一个点连接的点数为temp,那么two = C(temp,2); three是三个点相互连接的情况所以就是求两个点连同一个点有多少种情况,即求两个点连接的点的交集。然后ans = all-one+two+three就可以了。
one里面包含two和three, two里面包含three什么的xjb容斥;
下面上代码(参考hq):
#include<cstdio>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<set>
#include<map>
#include<queue>
#include<deque>
#include<vector>
#include<algorithm>
#include<cctype>
#include<math.h>
#include<stdlib.h>
#include<stack>
#include<ctime>
#include<bitset>
#include<list>
#define mst(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x)&(-x)
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pii pair<int,int>
#define eps 1e-3
const long long N = 1e12;
const long long mod=(long long)1e9+7;
const int INF=0x3f3f3f3f;
const long long LINF=(1LL<<62);
typedef long long LL;
typedef unsigned long long ULL;
//#define LOCAL
const double PI = acos(-1.0);
const int maxn=5e3+5;
const double g = 10;
using namespace std;
LL n,m;
LL u[20005], v[20005];
bitset<maxn> b[maxn], kk;
int main()
{
#ifdef LOCAL
freopen("test.txt", "r", stdin);
#endif // LOCAL
//ios::sync_with_stdio(false);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int T, cas = 0; scanf("%d", &T);
while(T--){
scanf("%lld%lld", &n,&m);
for(int i = 1; i <= n; i++) b[i].reset();
for(int i = 1; i <= m; i++){
scanf("%lld%lld", &u[i],&v[i]);
b[u[i]][v[i]] = 1; b[v[i]][u[i]] = 1;
}
LL all = n*(n-1)*(n-2)/6, two = 0, three = 0;
LL one = m*(n-2);
for(int i = 1; i <= n; i++){
LL temp = b[i].count();
two+=temp*(temp-1)/2;
}
for(int i = 1; i <= m; i++){
kk = b[u[i]]&b[v[i]];
three+=kk.count();
}
three/=3; //会有重复选到的情况所以/3;
printf("Case #%d: %lld\n", ++cas, all-one+two-three);
}
return 0;
}
ps:蟹蟹各位大佬帮助。