Graph Theory Notes

Graph Theory

Minimum spanning tree

$ N $ city, $ M $ bars can repair the roads, and each road has a repair cost of $ w_i $, $ N $ to make the city connectivity, the required minimum cost?

It requires a minimum of $ N-1 $ edges form a tree.

## Kruskal algorithm prove

On top of $ n $ point and figure to do induction, prove that $ Kruskal $ $ n $ algorithm for any graph of order applies

Induction base

$ N = 1 $, apparently to find a minimum spanning tree

Induction process

example

P1550 [USACO08OCT] Watering Hole drilling

The idea is to build a super source to each point to build a side for the $ w_i $ right side, and then run the minimum spanning tree

Demonstrate how the product can be divided into a number of co-primes

Not write, I too dishes

Seeking the path points on the right side of the minimum spanning tree maximum

int f[N][20]; //i的第2^j祖先
int mn[N][20]; //i往上跳2^j祖先所经过的边的最小值 
int query(int u,int v) {
    int ans=inf;
    if(dep[u]>dep[v]) swap(u,v);
    for(int i=0,k=dep[v]-dep[u];i<=LG[k];++i)
        if(k>>i&1) {
            ans=min(ans,mn[v][i]);
            v=f[v][i];
        }
    if(u==v) return ans;
    for(int i=LG[dep[u]];i>=0;--i)
        if(f[u][i]!=f[v][i]) {
            ans=min(ans,min(mn[u][i],mn[v][i]));
            u=f[u][i],v=f[v][i];
        }
    ans=min(ans,min(mn[u][0],mn[v][0]));
    return ans;
}

kruskal reconstruction tree

orz lgj seniors, seniors turned out to be a blog

Shortest

SPFA forfeit ring

queue<int> q;
bool inq[N];
int dis[N], len[N];
bool spfa() { //返回值为true表示有负环 否则没有负环 
    fill(dis+1,dis+n+1,inf);
    dis[1]=0,len[1]=1;
    q.push(1);
    inq[1]=true;
    while(!q.empty()) {
        int u=q.front() ; q.pop();
        inq[u]=false;
        for(int i=0;i<e[u].size();++i) {
            int v=e[u][i];
            int w=W[u][i];
            if(dis[u]+w<dis[v]) {
                dis[v]=dis[u]+w;
                len[v]=len[u]+1;
                if(len[v]>=n) return true;
                if(!inq[v]) q.push(v),inq[v]=true;
            }
        }
    }
    return false;
}

Map building skills

By means of adding virtual points, etc. The problem is transformed

So as to achieve the purpose of reducing the number of equilateral.

Sao operation, long exposure

Topological sorting

In a $ the DAG $ directed acyclic graph), we vertices in the graph in a linear manner to sort, so that for any vertex $ U $ to $ V $ directed edge $ (u, v) $, are You may have front $ u $ in $ v $ of.

//拓扑排序 O(n^2)
int ind[N]; //每个点的入度
int seq[N],cnt; //求出的拓扑序
bool vis[N];
bool toposort() { //有环返回false 
    while(true) {
        if(cnt==n) return true;
        int k=0;
        for(int i=1;i<=n;++i)
            if(!vis[i]&&ind[i]==0) {
                k=i; break;
            }
        if(k==0) return false;
        seq[++cnt]=k; vis[k]=true;
        for(int i=0;i<e[k].size();++i) {
            int u=e[k][i];
            --ind[u];
        }
    }
}

queue optimization

$O(n+m)$

//拓扑排序 O(n+m)
queue<int> q; //q中维护入度为0的点 
int ind[N],seq[N],cnt;
bool toposort() { //有环返回false
    for(int i=1;i<=n;++i)
        if(!ind[i]) q.push(i);
    while(!q.empty()) {
        int u=q.front(); q.pop();
        seq[++cnt]=u;
        for(int i=0;i<e[u].size();++i) {
            int v=e[u][i];
            --ind[v];
            if(ind[v]==0) q.push(v);
        }
    }
    return cnt==n;
}

tarjian

int dfn[N],low[N],dfsclock;
int s[N],top;
int cnt; //当前联通块的编号
int bl[N]; //bl[i]表示i所在的强联通分量编号 
vector<int> scc[N]; //scc[i]中存储编号为i强联通分量中的所有点
void dfs(int u) {
    low[u]=dfn[u]=++dfsclock;
    s[++top]=u;
    for(int i=0;i<e[u].size();++i) {
        int v=e[u][i];
        if(dfn[v]) low[u]=min(low[u],dfn[v]);
        else {
            dfs(v);
            low[u]=min(low[u],low[v]);
        }
    }
    if(low[u]==dfn[u]) {
        ++cnt;
        int v=s[top];
        while(v!=u) {
            bl[v]=cnt;
            scc[cnt].push_back(v);
            v=s[--top];
        }
        bl[u]=cnt;
        scc[cnt].push_back(u);
    }
}

## point reduction

In a strongly connected components as if the point is a big point, then, can become FIG directed acyclic graph (the DAG $ $), then what would facilitate the recursive

Differential Constraints

After write it, I feel that this is the right inequality set up a map ... I am too weak

Tree collar / group tree ring

We know that the tree is the most simple undirected graph connectivity.

There is only one path between any two points in the tree

Collar tree / tree cycloalkyl group: a tree Cato side.

One side is provided plus $ (u, v) $, $ u then made before, there is a path between v $, this edge after the addition of this path and this edge to form a ring.

This is also the only one of the rings is formed

We can put on view of the central ring, so that each point on the ring seems is a root.
The location is very important to find the ring

Similar approach $ noip2016 information transfer $

Get Tree ring base ring

Find the ring steps:

1. free to find a spot start as tree $ dfs $, and record each node access timestamp $ dfn $

2. $ dfs $ process there will be a point in $ dfn $ to even the edges than their smaller point, then this can be seen as plus side of that one. Record this edge $ (u, v) $

3. Violence Let $ u $ and $ v $ move up to the root, respectively, after recording their point.

4. They have been the deepest point of their $ lca $, $ u-> all points between lca $ + $ all points between v-> lca $ i.e. form a ring.

//求基环树中的环 方法一
int fa[N]; //f[i]为i在搜索树中的父亲结点 
bool in[N],vis[N]; //表示i是否在环中
int cir[N],cnt;
int x,y;
void dfs(int u,int f) { //f为u的父亲结点 
    fa[u]=f; vis[u]=1;
    for(int i=0 ;i<e[u].size();++i) {
        int v=e[u][i];
        if(v==f) continue;
        if(vis[v]) x=u,y=v;
        else dfs(v,u);
    }
}
void solve() { //x到y一定是返祖边 
    dfs(1,0);
    while(x!=y) {
        cir[++cnt]=x;
        x=fa[x];
    }
    cir[++cnt]=y;
}
//方法二
queue<int>q;
int deg[N],n;
void solve()
{
    for(int i=1;i<=n;++i) in[i]=1;
    for(int i=1;i<=n;++i)
        if(deg[i]==1) q.push(i);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        int[u]=0;
        for(int i=0;i<e[u].size();++i)
        {
            int v=e[u][i];
            deg[v]--;
            if(deg[v]==0) q.push(v);
        }
    }
    int u;//u作为环的起点
    for(u=1;u<=n;++u)
    if(in[u]) break;
    int v=u,las=0;//把u放环里
    do{
        cir[++cnt]=v;
        int k;
        for(i=0;i<e[v].size();++i)
        {
            k=e[v][i];
            if(in[k] && k!=las) break;
        }
        la
        v=k;
    }while(v!=u)
}

Euler

By drawing lines one and only one passage through all the edges of all vertices is called the Euler path.

By drawing lines one and only one loop through all the edges of all vertices is called Euler.

FIG referred to as having Euler Euler FIG.

FIG passage having Euler called semi-Euler FIG.

There can be defined similarly to the time of FIG.

$ G $ is Euler if and only if $ G $ is odd and not vertices of communication.

$ G $ semi Euler if and only if $ $ G there are exactly two odd degree vertices.

certificate:

And no communication of odd vertices => there must be a ring

Then we delete the edge on the ring, the rest of the communication and still meets FIG no odd vertices

The connectivity rings may be a common point and to be put together

Snare loop algorithm

$ Dfs $ search, can not then go down (can not be reused an edge, but can be repeated after a point) will be back, recording path backtracking, backtracking is not clear mark on the side, and finally find out the path is the Euler .

To edge number with $ vis $ array record whether each side visited

//欧拉回路 圈套圈算法
struct edge
{
    int v,nex,id;
};
bool vis[N];
int s[N],top;
int seq[N],cnt;
void dfs(int u)
{
    s[++top]=u;
    for(int i=head[u];i;i=e[i].nex)
    {
        if(vis[e[i].id]) continue;
        vis[e[i].id]=true;
        dfs(e[i].v);
    }
    --top;
    seq[++top]=e[i].v;
}

Guess you like

Origin www.cnblogs.com/pyyyyyy/p/11329739.html