1 #include<iostream> 2 #include<string> 3 #include<bitset> 4 5 6 using namespace std; 7 int N, M; 8 9 bool visited[1000]; 10 bitset<1'000> *map; 11 12 double percent(const bitset<1000> &src, int n) {//求一个人的n度认识人的集合 13 bitset<1000> totest(src); 14 bitset<1000> next; 15 bitset<1000> target(src); 16 17 do { 18 for (int i = 0; i < N; ++i) { 19 if (totest.test(i)) {//如果某位不为0 20 next |= map[i]; //next和map[i]相或,next就是根据xx你可以认识的人 21 } 22 } 23 target |= next;//targe和next或 24 totest ^= next; //异或得到差集 25 next.reset();//filp是翻转,~ 26 27 --n; 28 } while (n != 0); 29 30 return target.count() / (double)N; 31 32 } 33 34 35 36 int main() { 37 //freopen("in.txt", "r", stdin); 38 int a, b; 39 cin >> N >> M; 40 41 //bitset<1'000> *map = new(0x0) bitset<1000>[1000];//初始值为0 42 map = new bitset<1000>[1000];//初始值为0 43 44 for (int i = 0; i < M; ++i) { 45 cin >> a >> b; 46 map[a-1][b-1] = 1; 47 map[b-1].set(a-1); //同上 48 49 }//创建图 50 51 for (int i = 0; i < N; ++i) { 52 printf("%d: %.2lf%%\n", i+1, percent(map[i],5)*100); 53 } 54 55 56 return 0; 57 }
先上代码,我不会把每道题都上传解析,但是如果我觉得有不错的收益,或者认为写的够好,可能会考虑发上来记下,主要也是一个学习记忆的过程.
题目意思: 求一个人根据6层关系能够认识的人占所有人的比例,一个有关图的求解问题.基本解题思路不难,主要是我这里创新了一把.STL中的bitset,位图集合,图的模型是位图矩阵.
思路: 按位或可以求得并集,异或可以求得差集,与可以求得交集,取反可以求得补集.一个人能通过 六层关系认识的人 就是 5层以内认识的人(含自己)的朋友的并集.
按照这个思路,percent函数里,totest是一层新增朋友的的集合,注意是新增,为了确保新增,不需要进行不必要的循环或,24行代码求了一个差集,也就是说,如果我能在我已经认识乙了,就不再需要通过甲去认识乙.(这一步能省大量时间),其实也可以和target进行求差集,(更稳妥)
target储存所有朋友集合,每一次dowhile循环target就会求得一层朋友.
主要使用了bitset,操作集包括与,或,异或,[]被重载为返回某一位的引用,不过这个应该是返回的是封装了的对象,因为原生没有位,效率不如bitset.test(),set,reset,这样.
改变了上面一点,以及把cin改成scanf后,时间竟然达到了恐怖的38ms,而且只有60行不到的代码,就是不好想出来,我真牛批.....,
时间上面,虽然是邻接矩阵,但是因为量不大,且位操作快,主要也只是占用了额外空间,再就是按位与或没有区分长度.但是在这个量级速度远快于邻接链表等等.
翻了几页,连61ms都无人能够超越~