hdu 6016 Count the Sheep(枚举中点)
题意:
给你一个二分图,和一些边,问连接4个点的路线有多少条
题解:bc官方题解:
在此非常感谢验题组elfness对出题想法的帮助!
就是这题,为了保证本次BC难度足够友好,而换掉了另外一个质量还可以,不过大概难一些的题,让更多人2题保本o_o.
首先,因为朋友关系只能是在男羊和女羊之间的,所以这是一个二分图(当然,这个二分图性质并不重要)。
然后,我们发现每个序列都满足一端为男羊,另外一端为女羊,于是我们可以按照"女羊A,男羊B,女羊C,男羊D"的方式计数,在最后使得答案*2就好。
a[x]存是男羊x朋友关系的所有女羊,cnt[y]存女羊y拥有的男羊朋友数。于是:
for (int x = 1; x <= n; ++x) //枚举男羊B
{
LL onepoint = a[x].size() - 1; //除去女羊C,女羊A的可能方案数为a[x].size() - 1
for (auto y : a[x]) //枚举女羊C,这两层for循环其实只枚举了k条边,复杂度为o(n+m+k)
{
ans += (cnt[y] - 1) * onepoint; //显然除了男羊B,其他与C为朋友的男羊都可以作为男羊D,计数为cnt[y] - 1
}
}于是最后ans * 2就是答案啦。
PS: 对于边数很大的完全图在内的某些图时,计数会爆int。对于不算复杂度的暴力做法也会收获hacked或者tle。这是唯一有设计hack点的题目。以前hack多在01,这里把hack放在02怕大家爆零TwT真不容易。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef long long ll; 5 6 const int N=1e5+7; 7 int t,n,m,k,ain[N],bin[N],g[N],v[N],nxt[N],ed; 8 void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 9 10 int main(){ 11 scanf("%d",&t); 12 while(t--) 13 { 14 ll ans=0; 15 scanf("%d%d%d",&n,&m,&k); 16 F(i,1,n)g[i]=ain[i]=0; 17 F(i,1,m)bin[i]=0; 18 ed=0; 19 F(i,1,k) 20 { 21 int x,y; 22 scanf("%d%d",&x,&y); 23 adg(x,y); 24 ain[x]++,bin[y]++; 25 } 26 F(i,1,n)for(int j=g[i];j;j=nxt[j]) 27 ans+=1LL*(ain[i]-1)*(bin[v[j]]-1); 28 printf("%lld\n",ans*2); 29 } 30 return 0; 31 }