zoukankan      html  css  js  c++  java
  • 3月2-第八次机试课记录

    图论

    • dij使用地图是带权图

      • 记得初始化为INF
      • 无边的权值是INF,不是0,并且这个INF别用INT_MAX这个宏,会导致出现一些问题,比如dij更新路径的时候,INT_MAX + 1会变成负值,出错,自己定义一个比较大的数就行了
      const int INF = 1e9 + 7;
      

    思路与总结

    • 注意题目意识的转化,要把那些关键的信息抽象出来,比如小偷的移动东西就是可以抽象成为有向树,进而转化为找权值最大的树的根问题。
    • 其次要知道每个图相关的算法可以解决什么方面的问题,也就是你拥有那些工具:最短距离是找最短路径算法。涉及全局点的最优值,就是最小生成树。
    • 与图相关的算法
      • dfs/bfs
      • 最小生成树(prim + krusk)
      • 最短路径(dij + floyd)
      • 并查集
      • 拓扑排序
    • 注意初始化的值,不一定全是-1和0,比如dij的地图无法联通是INF
    • 无向图初始化要两次
    • 不仅是状态数组需要重新更新,地图在多组数据也要clear

    题号

    • PIPIOJ 1382: PIPI染色

    • PIPIOJ 1010: 好坑的电子地图

    • PIPIOJ 1117: 吝啬的PIPI

    • PIPIOJ 1384: PIPI的飞行路线

    • PIPIOJ 1182: 公交车站

    • PIPIOJ 1115: PIPI的聚会

    • PIPIOJ 1202: 侦探PIPI

    • PIPIOJ 1383: 院长PIPI

    • PIPIOJ 1183: 信使PIPI

    • PIPIOJ 1122: PIPI的比赛

    分析

    • 1010

      • 对地图的预处理,将不同奇数偶数的区别直接计算在地图上,ok了
    • 1117

      • 同样要对地图预处理
      • 同时这题在dij的时候搜索与更新路径是不一样的
        • 搜索是找最大保留路径
        • 更新是根据乘法更新路径信息
      • 这题还有个坑在与无法转账不是无法访问到这个点,而是最后的保留率为0,因为还可以包含给的数据直接收手续费全收取了
    • 1384

      • 使用优化的dij,主要在于使用矩阵的dij每次找最小点需要on的复杂度,现在使用优先队列,可以优化查询时间

      • 其次这题本来是打算使用dfs计算所有到达终点的路径,然后登记路径上可能的最大免费路径,但是答案给出的方法更加巧妙,使用两次dij,一次从起点到各个点,一次从终点到各个点,然后枚举免费路径,利用上面两个数组来维护最小开销

        //使用优先队列优化的dij
        struct Node{
        	int t;//对应点
        	int cost;//对应点的开销,不一定是最小,即为过程值,在过程中逐渐变为最优解
        	bool operator < (const Node &node) const{
                return cost > node.cost;//定义优先级
        	}
        }
        
        const int INF = 1e9;
        
        vector<Node> mp[N];//连接表
        int dist[N];//维护各个点的最小距离
        
        void dij(int s){
        	for(int i = 1; i <= n; i ++)
        		dist[i] = INF;
        	dist[s] = 0;
        	priority_queue<Node> Q;
        	Q.push({s, 0});
        	while(! Q.empty()){
        		Node now = Q.top();Q.pop();
        		
        		if(now.cost > dist[now.t])continue;//比最小的距离都大,没必要访问
        		//就是正常的更新路径
        		for(int i = 0; i < mp[now.t].size(); i ++){
        			Node next = mp[now.t][i];
        			if(dist[next.t] > now.cost + next.cost){//注意是now.cost不是dist[now.t]
        				dist[next.t] = now.cost + next.cost;
        				Q.push({next.t, dist[next.t]});
        			}
        		}
        	}
        }
        
        
        
    • 1115

      • 这题使用并查集,注意数据n和N是不一样的,朋友的下标并不在n之中,n只是查询的次数
    • 1202

      • 这题完全就是问题转化,如果将小偷的动向看成是有向图,那么问题就清楚起来的,也不用去考虑说动态的去找最优先,问题变成静态的找换或者找最多权的根
      • 使用并查集去达到这个目标
    • 1383

      • 这题就是问题的转化,从结果去想,所有的人一定都会加入,每两个的关系看成一条边,每加入一条边,就可以减去对应的费用,问题就转化成为了最小生成树(上面这个过程就是kruskal的过程)
      • kruskal过程需要借助并查集
    • 1183

      • 多次bfs将矩阵信息从地图矩阵中抽离出来,然后借助prim找最小生成树即可
      • 这题要区别bfs和最小生成树,bfs是在地图上跑的,而prim是在描述两者信息的矩阵上跑的,这题明显看出来
      • 其次,我本来想着一次bfs,然后最大的那个点的值就是结论,这样是错的,因为这样刚好是:当起点是最小生成树的中间点的时候,最小生成树的值刚好和bfs到最远点相同。但是起点不一定是中间点。
      • 我还想着多次bfs可以不用,一次bfs后,给每个教学楼打上时间戳,时间梯度差就是两点的距离,这样也是错的,还是最小生成树中间点是起点,两个端点a和b,a和b的最小距离可以是经过起点后才能计算,那么上面的结论完全错了,这个结论依赖两个端点直通才能有这个结论,如果不直通,那么就是错误的
    • 1122

      • 就是拓扑排序了,为了使得小的数字先数组使用了优先队列

        //优先队列是权值越大越先输出,即为递减队列
        priority_queue<int> Q;//默认是递减队列
        priority_queue<int, vector<int>, less<int> > Q;//等价于这个
        
        //递增队列
        priority_queue<int, vector<int>, greater<int> > Q;
        
  • 相关阅读:
    AngularJS Insert Update Delete Using PHP MySQL
    Simple task manager application using AngularJS PHP MySQL
    AngularJS MySQL and Bootstrap Shopping List Tutorial
    Starting out with Node.js and AngularJS
    AngularJS CRUD Example with PHP, MySQL and Material Design
    How to install KVM on Fedora 22
    Fake_AP模式下的Easy-Creds浅析
    河南公务员写古文辞职信
    AI
    政协委员:最大愿望是让小学生步行上学
  • 原文地址:https://www.cnblogs.com/faberry/p/12399083.html
Copyright © 2011-2022 走看看