模板之图论

来源:互联网 发布:方舟生存进化淘宝 编辑:程序博客网 时间:2024/06/01 09:37

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

最短路のSPFA:

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

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>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<<d[Te]<<endl;        for(int u=Te;u!=-1;u=prev[u]) cout<<u<<' ';        puts("");    }    else puts("-1");    return 0;}

次短路:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>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)            {                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<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>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_queue<heap>q;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<<d[Te]<<endl;    return 0;}

最小生成树のkruskal:

裸题村村通~

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>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.cost<b.cost;}void 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<<ans<<endl;    return 0;}

Tarjar 找scc:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>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<<ans;    return 0;}

倍增lca+树上前缀和:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>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]<deep[y])        swap(x,y);    if(deep[x]>deep[y])    {        int t=deep[x]-deep[y];        for(int i=24;i>=0;i--)            if(t&(1<<i))                x=father[x][i];    }    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;i<n;i++)    {        int 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<<x<<endl;        ans=dis[u]+dis[v]-dis[x]*2;         printf("%d\n",ans);     }    return 0;}

拓扑排序:

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>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;}
0 0