图论基础知识总结

Posted pkh68

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论基础知识总结相关的知识,希望对你有一定的参考价值。

图论基础知识总结

前言

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

代码


#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;
}

以上是关于图论基础知识总结的主要内容,如果未能解决你的问题,请参考以下文章

基础图论总结

图论的小总结

图论问题复习总结

基础图论知识总结

基础图论知识总结

专题四-图论总结