HDU 6016 Count the Sheep BestCoder Round #93 1002 边贡献统计
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6016
题意:给你一个二分图,计算长度为4的所有通路数(点各异)。
题解:这题一眼能想到的是枚举顶点作为端点,dfs搜索四层做统计,但是跑极限数据很容易出现O(n²)的复杂度。如果做树形dp处理的话,由于本人太弱不会处理圈,至于也想到统计边贡献,但是还是不知道怎么处理。赛后hack的时候,看了一眼别人的代码,发现智商又被压制了。
对于长度为4的通路,我们设为A-B-C-D,当一条边有贡献的时候,必然是处于A-B、B-C或者C-D(A-B、C-D一样)。这时显然能发现,如果把边作为A-B(或者C-D),又要进行dfs,也就是说复杂度分分钟都能上天了。如果把边看作B-C的话,只要与B相连的边数和与C相连的边数相乘即可。而且如果这样处理的话,会发现其实与B或者C 相连的边会默认成A-B或者C-D。综上所述,计算边的贡献的时候,只要把边看作B-C统计即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=100005;
int T;
int n,m,k;
ll ans;
int x[N],y[N],c[N*2];
int main()
{
cin>>T;
while(T--)
{
cin>>n>>m>>k;
memset(c,0,sizeof(c));
for(int i = 0 ;i < k; i++)
{
scanf("%d%d",x+i,y+i);
c[x[i]]++;
c[y[i]+n]++;
}
ans = 0;
for(int i = 0 ; i < k; i++)
ans += 2LL * (c[x[i]] - 1) * (c[y[i]+n] - 1);//减一是消掉自身的,乘2是因为每条通路方向有两个
printf("%I64d\n",ans);
}
return 0;
}