模板之图论

大神们都整理完了…我现在才来整理QAQ

最短路のSPFA:

可以判负环并且支持乱搞!
发一波最短路+判负环+记录路径(倒着输出)

#include
#include
#include
#include
#include
using namespace std;

const int MAX_V=2500+10;
const int MAX_E=5200+10;

int first[MAX_V],nxt[MAX_E<<1],d[MAX_V];
struct edge{
    int from,to,cost;
}es[MAX_E<<1];
int tot;
int V,E,Ts,Te;

void build(int ff,int tt,int dd)
{
    es[++tot]=(edge){ff,tt,dd};
    nxt[tot]=first[ff];
    first[ff]=tot;
}

bool vis[MAX_V];
int tim[MAX_V];
int prev[MAX_V];
queue<int>q;
bool spfa(int s)
{
    d[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=first[u];i!=-1;i=nxt[i])
        {
            int v=es[i].to;
            if(d[v]>d[u]+es[i].cost)
            {
                d[v]=d[u]+es[i].cost;
                prev[v]=u;
                if(!vis[v])
                {
                    if(++tim[u]>V) return false;
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return true;
}

int main()
{
    memset(first,-1,sizeof(first));
    memset(d,0x3f,sizeof(d));
    memset(prev,-1,sizeof(prev));
    scanf("%d%d%d%d",&V,&E,&Ts,&Te);
    for(int i=1;i<=E;i++)
    {
        int ff,tt,dd;
        scanf("%d%d%d",&ff,&tt,&dd);
        build(ff,tt,dd);
        build(tt,ff,dd);
    }
    if(spfa(Ts))
    {
        cout<for(int u=Te;u!=-1;u=prev[u]) cout<' ';
        puts("");
    }
    else puts("-1");
    return 0;
}

次短路:

#include
#include
#include
#include
#include
using namespace std;
const int SZ=200000+10;
int first[SZ],nxt[SZ<<1],d[SZ],d2[SZ];
struct edge{
    int from,to,cost;
}es[SZ<<1];
int tot;

void init()
{
    memset(first,-1,sizeof(first));
    memset(d,0x3f,sizeof(d));
    memset(d2,0x3f,sizeof(d2));
    tot=0;
}

void build(int ff,int tt,int dd)
{
    es[++tot]=(edge){ff,tt,dd};
    nxt[tot]=first[ff];
    first[ff]=tot;
}

bool vis[SZ];
queue<int>q;
void spfa(int s)
{
    d[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=first[u];i!=-1;i=nxt[i])
        {
            int v=es[i].to;
            if(d[v]>d[u]+es[i].cost)
            {
                d2[v]=d[v];
                d[v]=d[u]+es[i].cost;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
            else if(d[v]d[u]+es[i].cost)
            {
                d2[v]=d[u]+es[i].cost;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
            else if(d2[v]>d2[u]+es[i].cost)
            {
                d2[v]=d2[u]+es[i].cost;
                if(!vis[v])
                {
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    init();
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        int ff,tt,dd;
        scanf("%d%d%d",&ff,&tt,&dd);
        build(ff,tt,dd);
    }
    spfa(1);
    if(d2[n]==0x3f3f3f3f)
        puts("-1");
    else
        printf("%d\n",d2[n]);
    return 0;
}

最短路のdijkstra:

发一波堆优化过的

#include
#include
#include
#include
#include
using namespace std;

const int MAX_V=2500+10;
const int MAX_E=6200+10;

int first[MAX_V],nxt[MAX_E<<1],d[MAX_V];
struct edge{
    int from,to,cost;
}es[MAX_E<<1];
struct heap{
    int u,v;
};
int tot;
int V,E,Ts,Te;

void build(int ff,int tt,int dd)
{
    es[++tot]=(edge){ff,tt,dd};
    nxt[tot]=first[ff];
    first[ff]=tot;
}

bool operator < (heap a,heap b)
{
    return a.v > b.v;
}

bool vis[MAX_V];
priority_queueq;

void dij(int s)
{
    d[s]=0;
    q.push((heap){s,0});
    while(!q.empty())
    {
        heap x=q.top();
        q.pop();
        int u=x.u;
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=first[u];i!=-1;i=nxt[i])
        {
            int v=es[i].to;
            if(d[v]>d[u]+es[i].cost)
            {
                d[v]=d[u]+es[i].cost;
                q.push((heap){v,d[v]});
            }
        }
    }
}

int main()
{
    memset(first,-1,sizeof(first));
    memset(d,0x3f,sizeof(d));
    scanf("%d%d%d%d",&V,&E,&Ts,&Te);
    for(int i=1;i<=E;i++)
    {
        int ff,tt,dd;
        scanf("%d%d%d",&ff,&tt,&dd);
        build(ff,tt,dd);
        build(tt,ff,dd);
    }
    dij(Ts);
    cout<return 0;
}

最小生成树のkruskal:

裸题村村通~

#include
#include
#include
#include
#include
using namespace std;

const int MAX_E=10000+10;

struct edge{
    int from,to,cost;
}es[MAX_E<<1];
int fa[100+10];
int cnt=0,ans=0,V;

int find(int x)
{
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}

bool cmp(edge a,edge b)
{
    return a.costvoid kruskal()
{
    for(int i=1;i<=V;i++) fa[i]=i;
    sort(es+1,es+cnt+1,cmp);
    for(int i=1;i<=cnt;i++)
    {
        int fx=find(es[i].from);
        int fy=find(es[i].to);
        if(fx!=fy)
        {
            fa[fx]=fy;
            ans+=es[i].cost;
        }
    }
}

int main()
{
    scanf("%d",&V);
    for(int i=1;i<=V;i++)
    for(int j=1;j<=V;j++)
    {
        int x;
        scanf("%d",&x);
        es[++cnt]=(edge){i,j,x};
    }
    kruskal();
    cout<return 0;
}

Tarjar 找scc:

#include
#include
#include
#include
#include
using namespace std;

const int SZ=200000+10;

int first[SZ],nxt[SZ<<1];
struct edge{
    int from,to,cost;
}es[SZ<<1];
int tot=0;

void build(int ff,int tt)
{
    es[++tot]=(edge){ff,tt};
    nxt[tot]=first[ff];
    first[ff]=tot;
}

int dfn[SZ],low[SZ],scc[SZ];
int cnt=0,tim=0;
int ans=0x3f3f3f3f;
stack<int>s;
void dfs(int u)
{
    low[u]=dfn[u]=++tim;
    s.push(u);
    for(int i=first[u];i!=-1;i=nxt[i])
    {
        int v=es[i].to;
        if(!dfn[v])
        {
            dfs(v);
            low[u]=min(low[u],low[v]);
        } 
        else if(!scc[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        cnt++;
        int cnt2=0;
        while(true)
        {
            int x=s.top();
            s.pop();
            scc[x]=cnt;
            cnt2++;
            if(x==u)
            {
                if(cnt2>1) ans=min(ans,cnt2);
                break;
            }
        }
    }
}

int main()
{
    memset(first,-1,sizeof(first));
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int tt;
        scanf("%d",&tt);
        build(i,tt);
    }
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i]) dfs(i);
    }
    cout<return 0;
}

倍增lca+树上前缀和:

#include
#include
#include
#include
using namespace std;
const int MAXN=50000+10;
int first[MAXN],nxt[MAXN<<1],dis[MAXN];
struct edge{
    int from,to,cost;
}es[MAXN<<1];
int tot;
int deep[MAXN],fa[MAXN],father[MAXN][30];
void init()
{
    memset(first,-1,sizeof(first));
    memset(dis,0x3f,sizeof(dis));
    tot=0;
}
void build(int ff,int tt,int dd)
{
    es[++tot]=(edge){ff,tt,dd};
    nxt[tot]=first[ff];
    first[ff]=tot;
}
void dfs(int u, int f)
{
    deep[u]=deep[f]+1;
    fa[u]=f;
    father[u][0]=f;
    for(int i=1;i<=24;i++)
        father[u][i]=father[father[u][i-1]][i-1];   
    for(int i=first[u];i!=-1;i=nxt[i])
    {
        int v=es[i].to;
        if(v==f) continue;
        dis[v]=dis[u]+es[i].cost;
        dfs(v,u);
    }
}
int lca(int x,int y)
{
    if(deep[x]if(deep[x]>deep[y])
    {
        int t=deep[x]-deep[y];
        for(int i=24;i>=0;i--)
            if(t&(1<if(x!=y)
    {
        for(int i=24;i>=0;i--)
        {
            if(father[x][i]!=father[y][i])
            {
                x=father[x][i];
                y=father[y][i];
            }
        }
    }
    else return x;
    return father[x][0];
}
int main()
{
    init();
    int n;
    scanf("%d",&n);
    for(int i=1;iint ff,tt,dd;
        scanf("%d%d%d",&ff,&tt,&dd);
        build(ff,tt,dd);
        build(tt,ff,dd);
    }
    int m;
    scanf("%d",&m);
//  deep[1]=1;
    dfs(0,0);
    int u,v;
    for(int i=1;i<=m;i++)
    {
        int ans=0;
        scanf("%d%d",&u,&v);
        int x=lca(u,v);
        //cout<
        ans=dis[u]+dis[v]-dis[x]*2; 
        printf("%d\n",ans); 
    }
    return 0;
}

拓扑排序:

#include
#include
#include
#include
#include
using namespace std;

const int SZ=100100;

int rd[SZ];
int ans,n,m;
struct edge{
    int from,to;
}es[SZ];
int tot,first[SZ],nxt[SZ];

void build(int ff,int tt)
{
    es[++tot]=(edge){ff,tt};
    nxt[tot]=first[ff];
    first[ff]=tot;
}

queue<int>q;
void sort()
{
    for(int i=1;i<=n;i++)
        if(!rd[i])
        {
            printf("%d ",i);
            q.push(i);
        }
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=first[u];i!=-1;i=nxt[i])
        {
            int v=es[i].to;
            rd[v]--;
            if(!rd[v])
            {
                printf("%d ",v);
                q.push(v);
            }
        }
    }
}

int main()
{
    while(~scanf("%d",&n))
    {
        memset(first,-1,sizeof(first));
        int t;
        for(int i=1;i<=n;i++)
        {
            while(scanf("%d",&t)&&t)
            {
                rd[t]++;
                build(i,t);
            }
        }
        sort();
    }
    return 0;
}

你可能感兴趣的:(汇总,学习笔记)