洛谷P2419 [USACO08JAN]牛大赛Cow Contest
传递闭包 图论 STL bitset
题意 给出若干对排名关系 求有几个人的排名是可以确定的
这是图论中经典的传递闭包问题
首先对 x > y 我们建图 即 x 向 y连一条边 连一条单向边
这样我们跑floyd 就知道有几个点 能够到达他,以及他能到达的点
他能到达的点表示 有几个点确定比他小 能到的点 表示有几个点 确定比他大
然后如果 比他大的点和比他小的点和为 n+1 则这个点排名确定
这样floyd 一下就行
然后我们还可以用 bitset 位运算一下 加速一下
不用bitset 的 时间复杂度 为 O(n^3)
用了话就是 (n^3/w) 为什么 /w 因为 bitset 转化成了一位一位的二进制位
而 计算机 一次 & | 位运算 可以处理 8 位(按计算机而定) 一次|8位
所以要除以 w
相当于 你一定位数把他变成一个十进制数 压位一下 一个数代表好几位 然后 | 一下
就一次把好几位都处理掉了 其实bitset 就是 位运算 状态压缩
至于w等于多少,这个。。。我也不是很清楚 大概是8 或者32吧
但是bitset 比 用布尔数组 的常数大不少
应该说各有利弊吧
当然最好还是自己手写压位 然而我是懒人 懒得写啊
1 #include <cstdio> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <iomanip> 7 #include <iostream> 8 #include <bitset> 9 using namespace std ; 10 11 const int maxn = 111 ; 12 bitset <maxn> f[maxn] ; 13 int n,x,y,m,ans ; 14 15 inline int read() 16 { 17 char ch = getchar() ; 18 int x = 0 , f = 1 ; 19 while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 20 while(ch>='0'&&ch<='9') { x = x*10+ch-48 ; ch = getchar() ; } 21 return x * f ; 22 } 23 24 int main() 25 { 26 n = read() ; m = read() ; 27 for(int i=1;i<=m;i++) 28 { 29 x = read(),y = read() ; 30 f[x][y] = 1 ; 31 } 32 for(int i=1;i<=n;i++) f[i][i] = 1 ; 33 for(int k=1;k<=n;k++) 34 for(int i=1;i<=n;i++) 35 if( f[i][k] ) 36 f[ i ]|=f[ k ] ; 37 for(int i=1;i<=n;i++) 38 { 39 int sum = f[ i ].count() ; 40 for(int j=1;j<=n;j++) 41 if(f[ j ][ i ]) sum++ ; 42 if(sum==n+1) ans++ ; 43 } 44 printf("%d ",ans) ; 45 return 0 ; 46 }