hdu 6016 Count the Sheep(枚举中点)

题目链接: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真不容易。

 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 }
View Code

 

posted @ 2017-02-25 21:59  bin_gege  阅读(187)  评论(0编辑  收藏  举报