题目:
三元环
(three.cpp/in/out 2s 256M)
输入一个有向图的邻接矩阵,求有多少个三元环(A到B,B到C,C又回A)
'+'表示从第i行指向第j列的有向图(表示i到j),'-'无任何意义
Input
第一行给出数字N,3<=N<=1500.接下来N行N列给出数字矩阵
Output
如题
Sample Input
4
--+-
+--+
-+--
--+-
Sample Output
2
开两个bitset数组a[i]和b[i]。对于从i指向j的边,
我们令a[i][j]=1,b[j][i]=1,表示i→j存在,j→i也存在,这样a[i]表示从i发出
的终点的集合,b[i]表示到达i的边的起点的集
合。然后枚举边,对于边i→j,只要将a[j]和
b[i]并起来就是与这条边构成三元环的点集,
统计这些点集中点的个数ans,因为每个三元
环都要重复计算三遍,所以最后答案是ans/3
a[i]即为从i发出的点的集合,b[j]即为j接收到的点的集合
a[j]&b[i]表示中间的枚举点k,以i→k→j→i构成的三元环,这样的k会被我们枚举三遍,因为i,j也可以为K,同理k也可为i,j
图示如下:
code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 bitset<1510> a[1510],b[1510],p; 4 char mp[1510][1510]; 5 int n; 6 long long ans; 7 int main() 8 { 9 scanf("%d",&n); 10 for(int i=1;i<=n;i++) 11 for(int j=1;j<=n;j++) 12 cin>>mp[i][j]; 13 for(int i=1;i<=n;i++) 14 for(int j=1;j<=n;j++) 15 if(mp[i][j]=='+') 16 a[i][j]=b[j][i]=1; 17 for(int i=1;i<=n;i++) 18 for(int j=1;j<=n;j++) 19 if(a[i][j]) 20 { 21 p=a[j]&b[i]; 22 ans+=p.count(); 23 } 24 printf("%lld\n",ans/3); 25 return 0; 26 }