洛谷P2419 [USACO08JAN]牛大赛Cow Contest 传递闭包 图论 STL bitset

洛谷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\n",ans) ; 
45     return 0 ; 
46 } 

 

posted @ 2017-06-30 11:30  third2333  阅读(177)  评论(0编辑  收藏  举报