【图论基础模板】

//边链表
inline void insert(int u,int v,int w)
{
    e[++cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[cnt].v=w;
} 

//vector
vectot<int>    G[M];
inline void insert(int u,int v)
{
    G[u].push_back(v);
    G[v].push_back(u);
}

inline dfs(int x)
{
    vis[x]=1;
    for(int i=0;i<G[x].size();i++)
    {
        int v=G[x][i];
        if(!vis[v])        dfs(v);
    }
}


//遍历

inline dfs(int x,int fa)
{
    vis[x]=1;
    for(int i=head[x];i;i=e[i].next)
    {
        if(e[i].to!=fa && !vis[e[i].to])
            dfs(e[i].to,x);
    }
} 

inline bfs(int s)
{
    q.push(s);
    vis[s]=1;
    while(!q.empty())
    {
        int now=q.front();q.pop();
        for(int i=head[now];i;i=e[i].next)
        {
            if(!vis[e[i].to])
            {
                q.push(e[i].to);
                vis[e[i].to]=1;
            }
        }
    }
}


//最短路

//floyd
for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
            if(f[i][j]>f[i][k]+f[k][j])
                f[i][j]=f[i][k]+f[k][j];
        } 
        
//dijkstra
inline void dijkstra(int s)
{
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >
    for(int i=0;i<=n;i++)
        dis[i]=inf;
    dis[s]=0;q.push(make_pair(dis[s],s);
    while(!q.empty())
    {
        int now=q.top().second;q.pop();
        if(vis[now])    continue;
        vis[now]=1;
        for(int i=head[now];i;i=e[i].next)
            if(dis[now]+e[i].v<dis[e[i].to])
            {
                dis[e[i].to]=dis[now]+e[i].v;
                q.push(make_pair(dis[e[i].to],e[i].to));
            }
    }
}

//spfa
inline void spfa(int s)
{
    queue<int>    q;
    for(int i=1;i<=n;i++)
        dis[i]=inf;
    q.push(s);
    dis[s]=1;
    vis[s]=1;
    mark[s]++;
    while(!q.empty())
    {
        int now=q.front();q.pop();vis[now]=0;
        for(int i=head[now];i;i=e[i].next)
        {
            if(dis[now]+e[i].v<dis[e[i].to])
            {
                dis[e[i].to]=dis[now]+e[i].to;
                if(!vis[e[i].to])
                {
                    q.push(e[i].to);
                    mark[e[i].to]++;
                    if(mark[e[i].to]>=n)    return -1;//有负环 
                    vis[e[i].to]=1;
                }
            }
        }
    }
}


//并查集
inline int find(int x)
{
    if(fa[x]==x)    return x;
    else    return fa[x]=find(fa[x]);
}
for(int i=1;i<=m;i++)
{
    scanf("%d%d",&x,&y);
    int fx=find(x),fy=find(y);
    if(fx==fy)    continue;
    fa[fx]=fy;
} 


//kruskal
inline bool cmp(node x,node y)
{
    return x.v<y.v;
}
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
{
    int fx=find(a[i].x),fy=find(a[i].y);
    if(fx==fy)    continue;
    fa[fx]=fy;
    ++cnt;ans+=a[i].v;
    if(cnt==n-1)    break;
}

//topsort
for(int i=1;i<=m;i++)
{
    scanf("%d%d",&u,&v);
    d[v]++;
}
inline void topsort()
{
    int tot=n;
    for(int i=1;i<=n;i++)
    {
        if(!d[i])
        {
            q.push(i);
            tot--;
            t[++cnt]=i;
        }
    }
    while(!q.empty())
    {
        int now=q.front();q.pop();
        for(int i=head[now];i;i=e[i].next)
        {
            d[e[i].to]--;
            if(!d[e[i].to])
            {
                q.push(e[i].to);tot--;
                t[++cnt]=e[i].to;
            }
        }
    }
    if(tot)    return -1;//有负环 
}


//tarjan
for(int i=1;i<=n;i++)
    if(!dfn[i])        tarjan(i);
inline void tarjan(int x)
{
    dfn[x]=low[x]=++time;
    s[++s[0]]=x;
    vis[x]=1;
    for(int i=head[x];i;i=e[i].next)
    {
        if(!dfn[e[i].to])
        {
            tarjan(e[i].to);
            low[x]=min(low[x],low[e[i].to]);
        }
        else    if(vis[e[i].to])
            low[x]=min(low[x],dfn[e[i].to]);
    }
    if(dfn[x]==low[x])
    {
        vis[now]=0;num[bl[now]=++scc]=1;
        while(s[s[0]]!=now)
        {
            vis[s[s[0]]]=0;
            bl[s[s[0]]]=scc;
            num[scc]++;
                        s[0]--;
                }
                s[0]--;
    }
}

//割点
//u为割点    u->v 
//1.u为树根 且多于一个子树        2.low[v]>=dfn[u] 

////u->v 为桥
//low[v]>dfn[u] 

//lca(倍增)
inline void dfs(int now,int fa)
{
    for(int i=head[now];i;i=e[i].next)
    {
        if(e[i].to==fa)    continue;
        dep[e[i].to]=dep[now]+1;
        f[e[i].to][0]=now;
        minn[e[i].to][0]=e[i].v;
        dfs(e[i].to,now);
    }
}
inline void st()
{
    for(int i=1;i<=20;i++)
        for(int j=1;j<=n;j++)
        {
            f[j][i]=f[f[j][i-1]][i-1];
            minn[j][i]=std::min(minn[j][i-1],minn[f[j][i-1]][i-1]);
        }
}
inline int lca(int u,int v)
{
    if(dep[u]<dep[v])    swap(u,v);
    for(int i=20;i>=0;i--)
        if(dep[f[u][i]]>=dep[v])
            u=f[u][i];
    if(u==v)    return u;
    for(int i=20;i>=0;i--)
        if(f[u][i]!=f[v][i])
            u=f[u][i],v=f[v][i];
    return f[u][0];
}

//lca(树链剖分)
inline void dfs1(int now)
{
    sz[now]++;
    for(int i=head[now];i;i=e[i].next)
    {
        if(dep[e[i].to])    continue;
        dep[e[i].to]=dep[now]+1;
        fa[e[i].to]=now;
        dfs1(e[i].to);
        sz[now]+=sz[e[i].to]; 
    }
}
inline void dfs2(int now,int clain)
{
    top[now]=clain;
    int mxsz=0,pos=0;
    for(int i=head[now];i;i=e[i].next)
    {
        if(fa[e[i].to]==now)    continue;
        if(sz[e[i].to]>mxsz)
        {
            pos=e[i].to;
            mxsz=sz[e[i].to];
        }
    }
    dfs2(pos,clain);
    for(int i=head[now];i;i=e[i].next)
    {
        if(e[i].to==pos || fa[e[i].to]==now)    continue;
        dfs2(e[i].to,e[i].to);    
    }
}
inline int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])
            swap(x,y);
        x=fa[top[x]];
    }
    return dep[x]<dep[y]?x:y;
}

//欧拉回路
int cnt=1;
inline void insert(int u,int v)
{
    insert1(u,v);
    insert1(v,u);
} 
inline void dfs(int x)
{
    for(int i=head[x];i;i=e[i].next)
    {
        if(!vis[i])
        {
            vis[i]=vis[i^1]=1;
            dfs(e[i].to);
        }
    }
    s.push_back(x);
}
bool check()
{
    for(int i=1;i<=n;i++)
        if(d[i]&1)    return 0;//不是欧拉回路 
    return 1;
}

//差分约束系统
//x0+d<=x1    x0->x1 边权为d 
//x0+d>=x1    x1-d<=x0    x1->x0    边权为-d
//x0+d=x1    建两条边    x0+d<=x1    x0+d>=x1                

 

posted @ 2017-11-19 21:52  LittleOrange  阅读(168)  评论(0编辑  收藏  举报