zoukankan      html  css  js  c++  java
  • 图论题思考过程

    (在word里我都标了颜色。。。直接复制过来就没了 这里就不标了)

    注意边的数量

    初始化

    不能放过每一个条件 考虑如何实现  (emm。。。因为这句话19年山东省赛那个水题。。我思考了很久边到底有啥用。。。)

    图论多了解类型 这篇文章能解大部分吧。。  连通图的看lrj蓝书就好了

     2——sat :

    https://www.cnblogs.com/WTSRUVF/p/9791282.html

    在这

    其它的没写的 就多看看lrj蓝书

     

    二分图:

    普通匹配Dinic

    带权二分图 KM

    写之前一定要确定,我们要求什么,要用到什么。

    染色法:

    如果分为两队

    使每队里的人都相互认识  则不认识的两个人建边然后染色

    使每队里的人都不相互认识  则认识的两个人建边然后染色

    二分图中不存在奇环, 所以可以用染色法判断奇环

     

    把原图分成二分图且使子图的边数 >= m/2 则在染色一个的时候判断在这之前它和黑色、白色 哪个连的多,把它归为少的一方。

    最大匹配:二分图中边集的数目最大的那个匹配;

    最小顶点覆盖:用最少的点,让每条边都至少和其中一个点关联; = 最大匹配

    最小边覆盖:用尽量少的不相交简单路径覆盖有向无环图(DAG)G的所有顶点;  (本质就是求有向最长路径)=  顶点数 - 最大匹配

    最大独立集:在N个点的图G中选出m个点,使这m个点两两之间没有边的点中,m的最大值。 = 顶点数 - 最大匹配

     

    网络流:

    看到棋盘模型先来一套黑白染色冷静一下!!!

    用费用流实现控制次数的最短路

     

    最小割:

    满流的边即为要删除的边

    最小割即为最小价值损失

    对于指定要取的点,则它与源||汇点的边的权值为INF,表示不可满流,不可删除

    对于有联系的点,两点边权为他们的关系权值

    总权值加和 - Dinic() 即为答案

     

     

    无向图最小割

     

    预定义状态建边

    归类建边

    按时间点、时间段建边

    费用流 拆容量控制流量 费用为差值

     

    二分图多重最优匹配 Dinic

    二分图多重最大匹配 费用最大流

     

    有向环最小权覆盖

    有向环最小权覆盖是一个哈密顿回路,有环, 求的是在环中的边的和的最小值 Node[i].c == 0 的和的最小值  用KM或spfa

    如果是无向图  记得w[i][j] = w[j][i] = min(w[i][j], tmp); 

     最小边集覆盖(点不相交 每个点只在一条路上)

    最小边集覆盖是一个有向无环图,求的是n - max_flow, 即无环图的个数 用Dinic 或 匈牙利 hk

    最大权闭合子图

    有向图,每个点有点权,点权可正可负。对于任意一条有向边ij,选择了点i就必须选择点j,你需要选择一些点使得得到权值最大。 

     

    盈利在左边  花费在右边

    然后所有盈利 - 最大流 就是答案

    输出方案:

    如果左边的点i的d[i] != 0 则说明i被选择

    如果右边的点j的d[j] != 0 则说明j被选择

     

    最大密度子图

    s 向每条边建权值为1的边

    每条边向u和v建权值为INF的边

    每个点向t建权值为mid的边

    二分mid

    while(r - l > (1.0 / n / n))

    {

        double mid = (r + l) / (double) 2;

        build(mid);

        if(sum - Dinic() > eps) l = mid;

        else r = mid;

    }

    输出点集

    void f_dfs(int u)

    {

        for(int i = head[u]; i != -1; i = nex[i])

        {

            int v = Node[i].v;

            if(!vis[v] && Node[i].c > eps)

            {

                vis[v] = 1, f_dfs(v);

                if(v - m >= 1 && v - m <= n) ans++;

            }

        }    

    }

    然后 输出1 ~ n中被标记的点

     

    s - t平面图最大流

    (这个去参考一下那个国家队的论文。。。这个图就是那个的 看的时间太久远了忘了哪个了 百度吧。。。)

    s t之间连边

    里面的为s*  外面的为t*

    空地之间建边

    spfa

    连通图

     

    1、建图  2、缩点  [3、统计度数]

     

    遇到问是否u 能到 v啥的之类的  直接先一套连通图

    因为任意两个在一个连通图中的点都可以相互到达

    然后就算每个连通图之间都有边,那顶多就是一个有向无环图

     

    点双连通分量

    点不重复的路径、任意两条边都在同一个简单环中(无自环、无重边)、内部无割顶

    边双连通分量

    边不重复的路径、每条边都至少在一个简单环中、内部所有边都不是桥

     

    强连通分量缩点 能求有向无环最长路

    结合Dinic最小路径覆盖(点不相交) 求有几条

     

    环是最基本的连通分量

     

    在树中至少添加多少条边能使图变为双连通图。

    结论:添加边数=(树中度为1的节点数+1)/2

     

     

     

     

    最短路

     

    数据量大两点之间的最短路

    LCA + spfa

    1Lcadfs时处理出所有的非树边的点 存起来(dfs  v的时候 如果v已经被遍历过了那么 u v 都是非树边的点

    2、遍历所有非树边的点spfa求出到所有点的最短路dis[i][j] (第一维用非树边的点存在数组中的下标 (减少空间))

    3、对于每次询问(设非树边的点存在int a[maxn]中,且有ans个)

    int x = lca(u, v);

    LL res = dep[u] + dep[v] - 2 * dep[x];

    for(int i = 1; i <= ans; i++)

    {
    res = min(res, d[i][u] + d[i][v]);

    }

    printf(“%d ”, res);

    1、普通最短路双向 反向建边

    2、判断环路 (正环 负环)(dfs标记环路)  (解法:spfa 在进队后判断if(++ans[e.v] > n ) return 1;

    3、层次网络     (解法:因为分层,所以把层抽象为一个点,然后把本层的各点与层连线, 然后层与层之间连线 )

    4、差分约束  (spfa直接跑)

    求最大值: 对于不等式 x[i] - x[j] <= a[k],对结点 j 和 i 建立一条 j -> i的有向边,求最短路

    求最小值: 对于不等式x[i] - x[j] >= a[k],对结点 j 和 i 建立一条 j -> i的有向边,求最长路

     

    如果图不连通,则在spfa开始时,把所有的结点放进队列,如下代码

    无论求最大还是求最小 都这样写

    for(int i=1; i<=n; i++)

        {

            Q.push(i);

            d[i] = 0;

            vis[i] = 1;

    }

    注意下界  其它最短路无源也这么写

    注意隐含条件,一般都是相邻的两个点之间

    i 和 i + 1

     

    如果每个点都有个范围 设一个源点n + 1

    ZOJ 4028为例

    l <= a[i] <= r

    l <= a[i] - a[n - 1] <= r

     

    存在负环的话是无解 
    求不出最短路

    dist[ ]没有得到更新 (先判断是否有负环 再判断能否求出最短路 即是否为任意解  再输出正解

    if(spfa())

    printf("无解 ");

    else if(d[n] == INF)

    printf("任意解 ");

    else

    printf("%d ", d[n]);

     

      做差分约束一定要找个不等式关系,一般都有两个未知变量,像hdu1384  求的是与这个区间重合的元素,那我们就可以转化为sum(a)表示0到a区间与答案集合重合的元素

    然后sum(b) - sum(a - 1) >= w 或者 <= w 是不是就可以了  sum(a) 和 sum(b) 分别用a 和 b来表示就可以了

      像hdu 3666 有乘积的不等式 一定要想到log一下那么log(a) 和 log(b) 就可以分别用行和列来表示

     

    6、传递闭包(传递一种关系  用Floyd) 

    7、最大值最小化  

    if(d[e.v] > max(d[x],e.d))

    {

    d[e.v] = max(d[x],e.d);

    if(!vis[e.v])

      {

      Q.push(e.v);

         vis[e.v] = 1;

      }

     }

    最小值最大化

    if(d[e.v] < min(d[x],e.d))

    {

    d[e.v] = min(d[x],e.d);

    if(!vis[e.v])

      {

      Q.push(e.v);

          vis[e.v] = 1;

      }

     }

     

     

    8、分层最短路(dijkstra

     

    最小生成树

     

    步骤:

    先用Node存边

    按权值从小到大排序(如果有输出按字典序 则如果权值相等按u排,u还相等按v排)

    选取每条边并查集

    同时res += Node[i].w;

     

     

    多次询问两点间最短路的最大值最小化  最小瓶颈生成树

     

     

     

     

     

     

    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    Scala比较器---Ordered与Ordering
    WebSocket、Socket、TCP、HTTP区别
    WebSocket 是什么原理?为什么可以实现持久连接?
    写扩展性好的代码:函数
    Go语言的类型转换和类型断言
    go jwt OAuth2.0
    User Agent 里的各个字段含义
    前后端分离跨域问题解决方案
    beego + websocket 向页面推送数据
    beego orm关联查询之多对多(m2m)
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/11226959.html
Copyright © 2011-2022 走看看