1. 可达性统计

时间:半小时之内
https://www.acwing.com/problem/content/166/

思路:

  • 暴力,每一个点做一次dfs探查能到达多少个点
  • 拓扑排序加bitset记录能到达的点。A能到达B点,则A所能到达的点就是A这个点本身并上B所能到达的点,同理,B所能到达的点则为B这个点并上与B相连的点所能到达的点,如果一个点出度为0,该点只能到达它本身。因此,只需要做个拓扑排序(将所有边反向),第一次找出度为0的点,这些点可以直接确定所能到达的点,接着再继续更新与这些点相邻的点,为了便于直接查找哪些点到达这个出度为0的点,所以处理之前将所有边反向。

代码示例:

  1. #include <iostream>
  2. #include <bitset>
  3. #include <vector>
  4. #include <queue>
  5. using namespace std;
  6. struct Edge{
  7. int to;
  8. Edge(int _v){to = _v;}
  9. };
  10. typedef struct Edge Edge;
  11. int n, m;
  12. int deg[30005];
  13. bitset<30005> bs[30005];
  14. vector<Edge> revg[30005];
  15. void top_sort(){
  16. queue<int> que;
  17. for(int i = 1; i <= n; i++){
  18. if(deg[i] == 0){
  19. que.push(i);
  20. }
  21. }
  22. while(!que.empty()){
  23. int t = que.front();
  24. que.pop();
  25. bs[t].set(t, 1);
  26. for(int i = 0; i < revg[t].size(); i++){
  27. Edge e = revg[t][i];
  28. bs[e.to] |= bs[t];
  29. deg[e.to]--;
  30. if(deg[e.to] == 0){
  31. que.push(e.to);
  32. }
  33. }
  34. }
  35. }
  36. int main(){
  37. int a, b;
  38. cin>>n>>m;
  39. for(int i = 0; i < m; i++){
  40. cin>>a>>b;
  41. revg[b].push_back(Edge(a));
  42. deg[a]++;
  43. }
  44. top_sort();
  45. for(int i = 1; i <= n; i++){
  46. cout<<bs[i].count()<<endl;
  47. }
  48. return 0;
  49. }

2. 小猫爬山

https://www.acwing.com/problem/content/167/

思路:

  • 贪心,每次从第一个缆车开始找,能放的进就直接放(WA,过不了, 比如5 5 1 2 3 4 5这组数据)
  • 纯暴力,找出所有可能,TLE
  • 暴力+剪枝,AC。当次数超过答案,剪枝;当新加上一个缆车,剪枝,不需要再考虑放到更后面的缆车。

代码实现:

  1. #include <iostream>
  2. using namespace std;
  3. int n, w;
  4. int cats[20], cars[20];
  5. int ans = 0x3f3f3f3f;
  6. void dfs(int catpos, int cnt){
  7. // 不可能比最小值更小,返回
  8. if(cnt >= ans)return;
  9. if(catpos >= n){
  10. ans = min(ans, cnt);
  11. return;
  12. }
  13. for(int i = 0; i < n; i++){
  14. if(w - cars[i] >= cats[catpos]){
  15. // 有新加入缆车,那么需要的缆车数应为到当前缆车之前的车,否则数量不变
  16. int tcnt;
  17. if(cars[i] == 0)tcnt = i + 1;
  18. else tcnt = cnt;
  19. cars[i] += cats[catpos];
  20. dfs(catpos + 1, tcnt);
  21. cars[i] -= cats[catpos];
  22. }
  23. // 加入了新车,不考虑后边的缆车
  24. if(cars[i] == 0)break;
  25. }
  26. }
  27. int main(){
  28. cin>>n>>w;
  29. for(int i = 0; i < n; i++){
  30. cin>>cats[i];
  31. }
  32. dfs(0, n);
  33. cout<<ans;
  34. return 0;
  35. }

3.数独

4.