图论基础知识总结

图论基础知识总结

前言

因为博主太菜,好多之前学过的图论算法都要不记得了,于是开了这篇博文提醒自己要记得复习图论。

代码


#include<bits/stdc++.h>
using namespace std;

#define gc() getchar()
inline int In(){
    char c=gc(); int x=0,ft=1;
    for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1;
    for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0';
    return x*ft;
}
// get cut vertex and bridge
void dfs(int u,int fa){
    dfn[u]=low[u]=++dfs_clock;
    int child=0;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to;
        if(!dfn[v]){
            dfs(v,u); ++child;
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]) iscut[u]=1;
            if(low[v]>dfn[u]) // this edge is bridge
        }
        else if(v!=fa) low[u]=min(low[u],dfn[v]);
    }
    if(fa<0&&child==1) iscut[u]=0;
}
// get scc
void tarjan(int u){
    dfn[u]=low[u]=++dfs_clock;
    S[++S_top]=u; ins[u]=1;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to;
        if(!dfn[v]){
            tarjan(v,u); low[u]=min(low[u],low[v]);
        }
        else if(ins[v]) low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        int v; ++I_cntl
        do{
            v=S[S_top--];
            id[v]=I_cnt;
            ins[v]=0;
        }while(v!=u);
    }
}
// get bcc
// the bccno of the cut vertex is meaningless
void dfs(int u,int fa){
    low[u]=dfn[u]=++dfs_clock;
    int child=0;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to; Satus e=(Satus){u,v};
        if(!dfn[v]){
            S.push(e); ++child;
            dfs(v,u); low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u]){
                iscut[u]=1;
                ++bcc_cnt; bcc[bcc_cnt].clear();
                for(;;){
                    Satus x=S.top(); S.pop();
                    if(bccno[x.u]!=bcc_cnt){ bcc[bcc_cnt].push_back(x.u); bccno[x.u]=bcc_cnt; }
                    if(bccno[x.v]!=bcc_cnt){ bcc[bcc_cnt].push_back(x.v); bccno[x.v]=bcc_cnt; }
                    if(x.u==u&&x.v==v) break;
                }
            }
            else if(dfn[v]<dfn[u]&&v!=fa){
                S.push(e);
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    if(fa<0&&child==1) iscut[u]=0;
}
void find_bcc(){
    memset(dfn,0,sizeof(dfn));
    memset(iscut,0,sizeof(iscut));
    memset(bccno,0,sizeof(bccno));
    dfs_clock=bcc_cnt=0;
    for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i,-1);
}
// how to get ecc: 1.do dfs1 to get the bridge
// 2.do dfs2 that don't pass the bridge
// Two_sat
namespace Twosat{
    vector<int> G[N<<1];
    bool mark[N<<1];
    int S[N<<1],S_top;
    inline void init(){
        for(int i=0;i<2*n;++i) G[i].clear();
        memset(mark,0,sizeof(mark));
    }
    bool dfs(int x){
        if(mark[x^1]) return false;
        if(mark[x]) return true;
        mark[x]=true; S[++S_top]=x;
        for(int i=0;i<G[x].size();++i)
        if(!dfs(G[x][i])) return false;
        return true;
    }
    // x = xval or y = yval
    void Add_clause(int x,int xval,int y,int yval){
        x=x*2+xval; y=y*2+yval; G[x^1].push_back(y); G[y^1].push_bask(x);
    }
    bool Solve(){
        for(int i=0;i<n*2;i+=2)
        if(!mark[i]&&!mark[i+1]){
            S_top=0;
            if(!dfs(i)){
                while(S_top>0) mark[S[S_top--]]=false;
                if(!dfs(i+1)) return false;
            }
        }
        return true;
    }
}
// Dijkstra
void djikstra(int s){
    priority_queue<Node> Q;
    for(int i=1;i<=n;++i) d[i]=INF,done[i]=0;
    d[s]=0; done[s]=1; Q.push((Node){s,0});
    while(!Q.empty()){
        Node x=Q.top(); Q.pop();
        int u=x.u; if(done[u]) continue; done[u]=true;
        for(int i=h[u],v;i;i=e[i].nex){
            v=e[i].to;
            if(d[v]>d[u]+e[i].w){
                d[v]=d[u]+e[i].w;
                Q.push((Node){v,d[v]});
            }
        }
    }
}
// SPFA : he has died...
bool SPFA(int s){
    queue<int> Q;
    memset(inq,0,sizeof(inq));
    memset(cnt,0,sizeof(cnt));
    for(int i=1;i<=n;++i) d[i]=INF;
    d[s]=0; Q.push(s); inq[s]=1;
    while(!Q.empty()){
        int u=Q.front(); Q.pop(); inq[u]=0;
        for(int i=h[u],v;i;i=e[i].nex){
            v=e[i].to;
            if(d[v]>d[u]+e[i].w){
                d[v]=d[u]+e[i].w;
                if(!inq[v]){
                    Q.push(v); inq[v]=1;
                    if(++cnt[v]>n) return true;
                }
            }
        }
    }
    return false;
}
// directed tree
// if there isn' answer return -1
int Solve(){
    int ans=0,cnt;
    while(1){
        for(int i=1;i<=n;++i) _in[i]=INF;
        for(int i=1;i<=m;++i){
            int u=e[i].u,v=e[i].v;
            if(u!=v&&e[i].w<_in[v]) _in[v]=e[i].w,pre[v]=u;
        }
        for(int i=1;i<=n;++i) if(i!=root&&_in[i]==INF) return -1;
        cnt=0; for(int i=1;i<=n;++i) id[i]=vis[i]=0;
        for(int i=1;i<=n;++i){
            if(i==root) continue;
            ans+=_in[i]; int v=i;
            while(vis[v]!=i&&!id[v]&&v!=root){
                vis[v]=i; v=pre[v];
            }
            if(!id[v]&&v!=root){
                id[v]=++cnt;
                for(int u=pre[v];u!=v;u=pre[u]) id[u]=cnt;
            }
        }
        if(cnt==0) break;
        for(int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt;
        for(int i=1;i<=m;++i){
            int u=e[i].u,v=e[i].v;
            e[i].u=id[u]; e[i].v=id[v];
            if(id[u]!=id[v]) e[i].w-=_in[v];
        }
        root=id[root]; n=cnt;
    }
    return ans;
}
// Kruskal: insert the edge in the order that from min_w to max_w
// Prim: each times find the best point to add into the tree
// Dinic
namespace Dinic{
    int h[N],e_tot=0;
    struct E{ int to,nex,cap,flow; }e[M<<1];
    inline void add(int u,int v,int w){
        e[++e_tot]=(E){v,h[u],w,0}; h[u]=e_tot;
    }
    inline void Add(int u,int v,int w){
        add(u,v,w); add(v,u,0);
    }
    inline void bool bfs(){
        for(int i=s;i<=t;++i) cur[i]=h[i],vis[i]=0;
        queue<int> Q; Q.push(s); d[s]=0; vis[s]=1;
        while(!Q.empty()){
            int u=Q.front(); Q.pop();
            for(int i=h[u],v;i;i=e[i].nex){
                v=e[i].to;
                if(!vis[v]&&e[i].cap-e[i].flow>0){
                    Q.push(v); d[v]=d[u]+1; vis[v]=1;
                }
            }
        }
        return vis[t];
    }
    int dfs(int u,int las){
        if(u==t||las==0) return las;
        int flow=0,f;
        for(int i=h[u],v;i;i=e[i].nex){
            v=e[i].to;
            if(d[v]==d[u]+1&&(f=dfs(v,min(las,e[i].cap-e[i].flow)))>0){
                e[i].flow+=f; e[i^1]-=flow;
                las-=f; flow+=f; if(!las) break;
            }
        }
        return flow;
    }
    inline int max_flow(){
        int flow=0;
        while(bfs()) flow+=dfs(s,INF);
        return flow;
    }
}
int main(){

    return 0;
}

原文地址:https://www.cnblogs.com/pkh68/p/10540540.html

时间: 2024-11-05 21:27:07

图论基础知识总结的相关文章

图论基础知识.

今天先写一些基础的图论知识: 1.floyed算法: 2.spfa算法: 3.dijkstra(迪杰斯特拉)算法:(先不写) 1.floyed算法 可以找到任意两点之间的最短路,即dis[i][j]: 原理:图的传递闭包思想:时间复杂度:O(n*n*n); 思想也比较好理解(三角形任意两边之和大于第三边嘛,如果出现不符合,就更新距离,这样比较好想) 例题oj1212图G是一个无向连通图,没有自环,并且两点之间至多只有一条边.我们定义顶点v,u最短路径就是从v到u经过边最少的路径.所有包含在v-u

图论基础知识(1)-什么是图和图的分类

emmm......蒟蒻的第一篇博客,先讲一个比较简单的东西来熟悉以下操作吧(还是怕自己翻车) 由于本人知识水平有限,暂时不会涉及相关数学知识,这篇博客主要还是提供个人对图论的比较感性的认识 这篇文章将要介绍: 图的基本定义 图的简单分类 一些简单术语的解释 因为本人比较蒻,所以这篇博客会讲的非常慢,dalao们可以绕步了... Part1 什么是图: 这是百度百科里面给出的解释,很重要的一条就是:“这种图形通常是用来描述某些事物之间的某种特定关系”,也就是说图实际上存储的是一些关系,所以说以下

关于图算法 &amp; 图分析的基础知识概览

网址:https://learning.oreilly.com/library/view/graph-algorithms-/9781492060116/ 你肯定没有读过这本书,因为这本书的发布日期是2019年5月.本文会覆盖该书的大部分内容,读完这篇,你能够了解图算法的基本概念.关于此书,作为市面上为数不多的面向数据科学应用的图算法书籍,写的比较全面系统和易懂.当然,书在细节上的提高空间还有很多.今天内容很多,坐稳~ 目录 图算法 & 图分析 图基础知识 连通图与非连通图 未加权图与加权图 有

MySQL数据库基础知识

day02 MySQL数据库基础知识 一.基础知识概述: 基础决定你这门课程的学习成败!只有学习好这些基础知识以后,你才能真正的运用自如.才能够对数据库有更深入的了解,道路才会越走越远. 二.基础知识: 1.数据库(database):数据库就好比是一个物理的文档柜,一个容器,把我们整理好的数据表等等归纳起来. 创建数据库命令:        create database 数据库名; 2.查看数据库         show databases; 3.打开指定的数据库         use 

linux入门基础知识及简单命令介绍

linux入门基础知识介绍 1.计算机硬件组成介绍 计算机主要由cpu(运算器.控制器),内存,I/O,外部存储等构成. cpu主要是用来对二进制数据进行运算操作,它从内存中取出数据,然后进行相应的运算操作.不能从硬盘中直接取数据. 内存从外部存储中取出数据供cpu运存.内存的最小单位是字节(byte) 备注:由于32的cpu逻辑寻址能力最大为32内存单元.因此32位cpu可以访问的最大内存空间为:4GB,算法如下: 2^32=2^10*2^10*2^10*2^2 =1024*1024*1024

BroadcastReceive基础知识总结

BroadcastReceive基础知识总结 1.BroadcastReceive简介 BroadcastReceive也就是"广播接收者"的意思,顾名思义,就是用来接收来自系统和应用中的广播 在Android系统中,广播体现在方方面面,例如当开机完成后系统会产生一条广播,接收到这条广播就能实现开机启动服务的功能,当网络状态改变时,系统会产生一条广播,接收到这条广播,就能及时的做出提示和保存数据等操作,当电池的电量改变的时候,系统会产生一条广播,接收到这条广播就能在电量低的时候告知用户

基础知识--:before伪元素和:after伪元素

http://book.51cto.com/art/201108/285688.htm 3.7  替换指定位置 大家都知道before和after是前.后的意思.但是奇怪的是,CSS中的:before伪元素和:after伪元素是为源文档中不存在的内容设置样式的. 没有内容怎么设置样式呢?别急!它们有一个content属性,一起使用就可以为某个选择器前.后的内容设置样式了. 下面就来了解一下:before伪元素和:after伪元素的用法. 视频教学:光盘/视频/3/3.7  替换指定位置.avi 

20_Shell语言———VIM编辑器基础知识三之窗口属性定制、配置文件及查找替换功能

Vim编辑器可以让用户按照需求来定制一些使用属性. 一.窗口属性定义 1)显示行号 行号不是内容,只是用来帮助用户确认文本所在的行.在vim编辑器中,如果要显示行号,可以在末行模式下输入: set number 如果想关闭,则可以在功能名称前面加上no,即: set nonumber 命令可以被简写,如set number 可以简写为 set nu:set nonumber 可以简写为 set nonu. 注意,上述设定仅对当前vim的进程有效,一旦当前进程关闭,这些设定就会失效,如果要使设定永

web基础知识(一)关于ajax传值最基础东西

HTTP方法之 GET对比POST GET:从指定的资源请求数据, POST:向指定的资源提交要被处理的数据 GET方法: 请注意,查询字符串(名称/值对)是在 GET 请求的 URL 中发送的: /test/demo_form.asp?name1=value1&name2=value2 有关 GET 请求的其他一些注释: GET 请求可被缓存 GET 请求保留在浏览器历史记录中 GET 请求可被收藏为书签 GET 请求不应在处理敏感数据时使用 GET 请求有长度限制 GET 请求只应当用于取回