zoukankan      html  css  js  c++  java
  • 图论

    最短路

    (;)

    Problem

    (;)
    无向图,走(d)步能否到达,每个点拆成奇偶两个点考虑
    (但好像拆点比直接记0/1慢)

    次短路

    (;)
    正常是考虑到每个点的最短和次短路(f,g)
    尝试互相去转移。分类讨论好麻烦啊
    不妨跑两遍,(g)的更新初始用(f)来算,现在相当于把所有(f)(g)的影响算好了。
    然后再只考虑(g)(g)的影响,就在跑一遍最短路(大于(f)的前提下)

    同余最短路

    (;)
    给定(a_1,a_2,...,a_n),问有多少个(B),使得(a_1x_1+a_2x_2+...+a_nb_n=B)非负整数解
    我们不妨把(a_1)拿出来(其实任意一个都行),把所有的B按模(a_i)的余数分开考虑
    因为只要(ka_1+x)被凑出来了,那么所有((k+1)a_1+x,...)的数都可以被凑出来,相当于模(a_i)分到同一组内的数都可以由其中最小的那一个转移而来
    考虑求这个最小的数,也就是求最小的(k)
    一个(a_i),相当于建一条(x)->((x+a_i)\%a_1)的边,对于那种顶到右边界绕到左边的边权应该为1
    复杂度:(O(na_ilog a_i))

    优化建边方式

    映射到坐标轴上

    (;)
    两点距离为横坐标差和纵坐标差的较小值
    发现把点的坐标映射到(x)(y)轴上,那么我实际上要让它映射到的两个点看成同一个点,只不过是两种不同的转移方式
    那么显然只需要让在(x)轴上相邻的点连边,一个点映射的两个点间连一条边权为0的边
    (;)
    或是在坐标轴上跳时,和距离有关,不妨从(i)(i-1)连边

    数据结构优化

    (;)
    向一段区间内的点都连边
    正常是开一个中继点,这里可以采取线段树的方式。
    那么向线段树的对应节点连边
    或是分块,对于(l)个块到(r)个块,建一个点,这样总共有(O(n))个点
    零散块直接在坐标轴上维护前缀和后缀的辅助点

    bzoj4144

    (;)
    这道题好妙
    首先肯定要求出连接加油站的生成树(因为路径可以抽象经过一段段的路径,走到一些加油站)
    然后我们要防止在加油站之间死掉,也就是让这颗生成树上一条路径上最大的边最短(显然就是最小生成树)
    那么那些加油站之间可能连边呢?
    考虑原图的边,只有一条边所连的两个点属于的集合不同,那么这两个集合之间的加油站才可能连边。
    (这个证明大概就是中间如果隔着一个加油站,去那里加油会更优

    网络流

    卖猪问题

    (;)
    最开始比较好想的是分层图。
    按照顾客来的顺序去分层。
    但这样发现点数和边数会比较多,考虑优化
    一种是建图的优化
    1.多条inf的边串联或并联,那么之间变成一条
    2.可能有一条有限制的边和一条inf的边并联,直接改成一条inf的边
    3.如果发现有两两加边的情况,考虑在中间加个中继点
    还有另外一种建图的方式
    如果两个人之间有交集,发现前面的人可以给后面的人预支一些猪。
    其实相当于简化了过程。原先是人——>猪圈——>人,现在直接从人——>人
    但其实向下一个打开猪圈的人连边会更好(其实有点像把这个人作为中继点)

    SGU 326

    (;)
    贪心让1赢得尽可能多比较显然
    对于两队进行比赛的题目(往往就可以把比赛看成一个汇点(当然不是总汇点),向两队连边),所以只会把胜利分配给两队的其中一个
    虽然网络流无法判断是否把容量撑爆,但是可以看与源点相连的边是否满了即可

    POJ2699

    (;)
    这里不能把一个点拆成输赢了(因为只知道它赢了多少场不能判断它是否是king)
    发现n很小,就要尝试一些暴力的思路,比如说枚举,状压之类的。
    这里有一些特殊的性质,只用选分数最高的k个。
    因为我们要让得分高的先赢的多,这样感觉会更容易满足。
    还是刚刚的建图方式

    SGU 438

    (;)
    往往有一些网络流的题,会有一些像dp的阶段。
    比如:时间,顾客的人数。
    这种往往都是针对的全局的状态(即每个点的属性都会变成这样),像时间就是每个点都来到了这个时间。
    这道题,每个点都有限制,能不能按这个限制分层呢?显然不好做,因为每个点的限制是不一样的。
    但如果不分层呢?因为这道题中强调了时间的概念(即让时间尽可能短),而如果只是一层感觉不太好记录现在已经过了多长时间了)
    所以要把整体按时间分层。而ci的限制就在分层图中的每一层中拆点。(这样满足了"同时"的限制)
    一种简单的想法是,二分时间T,判断能否满流,但时间有些无法接受。
    还有一种比较好的思路是,因为我要最小化最大时间,所以只要有一个人到了比较大的时间,就会是答案不优。
    我们于是考虑费用,让T+1的费用至少是T的费用的100倍,但费用流也太慢
    所以考虑逐层加点,也就是动态网络流的过程,在残量网络上继续增广,这样只相当于改变了增广的顺序,对于dinic的复杂度还是没有影响的

    SPOJ 962

    (;)
    要求A到B,B再到C,且中途不能重复经过同一个点。
    是不是想到了传纸条那道题~
    所以我们只需要找两条路径,分别以A,C为起点,终点是B,要求不能有重叠的地方,那么显然可以拆点。
    闲的没事想了一下如果要经过A,B,C,D,E,F....这种题怎么做,发现不会。貌似不大能扩展

    HDU 5639

    (;)
    太神仙了这道题。
    乍一看,每次只能删去一颗基环树森林?什么玩意。
    但基环树有非常好的性质:即每个点只有一条出边。(这里我们把它看成内向树)
    所以每次,假如每个点唯一匹配了一条边,然后把这些边删去,一定能满足条件。
    (感觉又是一个映射的思路?其实也不大像,但可以这么类比)
    那么这若干轮,每个点可能会匹配到若干个点。
    假如我们已经确定了每个点所匹配的边的集合,那么显然最多的那个就是答案。
    让最大的最小,显然就可以二分(或是不断扩容),感觉后者更好一些,和比赛分配胜利一样的建图方式。

    HDU 1956

    (;)
    给定有向边和无向边,问:是否能给无向边分配方向,使得图中包含欧拉回路
    又是经典题
    先给无向图随机分配方向,考虑去动态调整
    发现(C)=出度-入度是偶数,是负数的就要从源点向它连边,反之则向汇点连边。
    然后将原图所有无向边反向建图,容量为1
    这样考虑从(S->x),每流大小为1的流,即:把这条流所流的路径上的边都反向过来,且中途经过的点的(C)不会边,且让终点和起点,分别想它们各自的目标靠近了1

    POJ2396

    (;)
    知道每行每列的和,各自整数的取值范围
    构造这样的矩阵
    考虑从S向行的关键点连边,T向列的关键点,每个点都向它所属的两个关键点连边。
    但此时有上下界的限制,于是考虑上下界网络流
    与普通的网络流只多了下界的限制,考虑怎么去除下界,剩余的就和正常的一样了。
    考虑先给他分配好了,那么现在会出现问题,即:流量不平衡。
    好,对于入>出,说明出去的边流量小了,于是考虑用源点向它加条边,那么就会流到出边上。
    否则,用汇点向这个点连边,那么入边的流量就不得不多了。

    BZOJ 1143

    (;)
    DAG,选最大的点集,使得两两不到达。
    DAG中,最长反链=最小链覆盖(这里是可以相交的)
    所以还得Floyd传递闭包(这玩意挺好用的,能弄出每对点的联通性)
    至于判断一组解,有一个比较好的思路。
    已知最优解是(k)个点
    我们暴力判断选出一个点之后,剩下的的点能否选出(k-1)个点就行了,且选完之后要把所有和这个点有偏序关系的点删去
    再在剩下的点所构成的若干个联通快上做,(k-2,k-3...)这样一定就能找到一组解了

    最小割

    切糕模型

    (;)
    这个东西非常的牛逼,可以扩展到很多问题。
    P3227:发现两个相邻位置的高度不能超过D,对应的是一个矛盾的关系。
    在建模的时候,我需要根据题目的需求来使发生矛盾后,是会付出一定的代价,还是根本不可行
    假如说,我们把原问题的中一个东西的代价看作图上的一条边。
    而切断这条边,看作选了这个东西,并付出代价(注意这里边所代表只能是代价,而不能是价值),因为没有最大割这个东西
    而我们通过一系列高超的建模,又能使每一种方案都能且必须把这张图切断,就可以转化为最小割问题。
    对于切糕模型,基本对于两者矛盾的关系,需要构造出两条链,而选了一个A链的前缀和B链的后缀中的点,会导致产生矛盾。
    于是在两条链之间竖着加一条边,容量为(INF)或是(c),按题目而定。
    这道题就需要从((i,j,k))((i,j,k+D))去构造一条容量为(INF)的边

    BZOJ1934

    (;)
    每个小朋友有两种选择,每种选择可能对应着一定的代价,就不妨把每种选择看成一条边,尝试去割。
    与原意愿不符为1,否则为0
    且发现两个好朋友如果选择不同(这里就变成了一段前缀和后缀),当然要付出1的代价,连边。

    POJ2987

    (;)
    上司被裁,员工也被裁,感觉可以建出上司->员工的边。
    但这样不好。
    套用切糕模型,有裁或不裁两种。
    和上题一样。但有两点不同
    1.中间的边是(INF),因为题目是不允许
    2.这里是价值而不是收益,所以先把会贡献正收益的选上,那么如果裁掉他,相对那么会挣0的钱,否则就要退还,即付出代价。
    对于负收益的,显然可以直接套用。
    感觉这样是先算后退的样子

    HDU1569

    (;)
    每个格子选或不选,但这里是两个前缀的矛盾,所以直接黑白染色,对于黑色把选放在前缀,白色把选放在后缀,然后先算后退就可以

    BZOJ1001

    (;)
    臭名昭著(bushi)的狼抓兔子。
    发现把一个正方形的分成的两个三角看作2个点,然后把图上跨过一条边的点对连边。
    那么可以把一个割,看作从(S)(T)的任意一条路径,那么求最短路即可。
    好像是什么转对偶图后,原图最小割=对偶图最短路

    BZOJ1070

    (;)
    按维修人员考虑,显然倒数第(k)个车会贡献(k)倍的代价
    那么直接费用流解决(这道题有一些提前算贡献的思路)

    Vijos1891

    (;)
    一道按照费用流本质出的题,目前还不会,挖个坑

  • 相关阅读:
    Mysql元数据分析
    python编码encode和decode
    自己写的Python数据库连接类和sql语句拼接方法
    【甘道夫】Sqoop1.99.3基础操作--导入Oracle的数据到HDFS
    SVN配置以及自己主动部署到apache虚拟文件夹
    css中使用id和class 的不同
    Android OpenGL ES(七)----理解纹理与纹理过滤
    一键安装 redmine on windows 和发邮件设置
    足球大数据:致足球怀疑论者-The Counter(s)-Reformation反教条改革
    【Android进阶篇】Fragment的两种载入方式
  • 原文地址:https://www.cnblogs.com/czyty114/p/15150906.html
Copyright © 2011-2022 走看看