• tulun


    图论

    1.建图

    1.邻接矩阵

    (例:map[i][j]——————表示编号为i的点与编号为j的点有边。)

    2.邻接表 (未学);

    3.边集数组 (最常用)

    代码

    struct node
    {
        int a,b,nx,c;
    }t[100010];
    int head[100010],n,nz;
    
    void Build edge()
    {
        int a,b,c;
        for(int i=1;i<=n;i++)
        {
            t[++nz].a=a;
            t[nz].b=b;
            t[nz].c=c;
            t[nz].nx=head[a];
            head[a]=nz;
        }
    }
    

    2.最短路径算法

    1.单源最短路径

    1.Dijkstra

    代码

    1.邻接矩阵

    void dijkstra(int s)
    {
        int i,j,Min,p;
        for(i=1;i<=n;i++)d[i]=inf;
        d[s]=0;v[s]=true;
        for(j=1;j<=n;j++)
        {
            Min=inf;
            for(i=1;i<=n;i++)
                if((!v[i])&&(d[i]<Min)){Min=d[i];p=i;}
            v[p]=true;
            for(i=1;i<=n;i++)
                if(a[p][i]!=0&&d[i]>d[p]+a[p][i])
                    d[i]=a[p][i];
        }
    }
    

    2.边集数组

    void dijkstra(int s)
    {
        int i,j,k,Min,v;
        memset(vis,false sizeof(vis));
        for(i=0;i<=n;i++)h[i]=inf;
        h[s]=0;
        for(i=1;i<=n;i++)
        {
            Min=inf;k=-1;
            for(j=1;j<=n;j++)
                if((vis[j]==false)&&(Min>h[j]))
                {
                    Min=h[j];
                    k=j;
                }
            if(k==-1)break;
            vis[k]=true;
            j=head[k];
            while(j!=-1)
            {
                v=t[i].v;
                if(h[v]>h[k]+t[i].c)h[v]=h[k]+t[i].c;
                j=t[i].nx;
            }
        } 
    }
    

    2.spfa(可判断负环)

    int spfa(int src,int n)
    {
        int i;
        for(i=1;i<=n;i++)
        {
            vis[i]=0;
            dis[i]=inf;
        }
        dis[src]=0;
        int q[110],l=1,r=1;
        q[src]=src;
        vis[src]=true;
        while(l<=r)
        {
            int u,v;
            u=Q[l];
            vis[u]=false;
            for(i=head[u];i>=0;i=t[i].nx)
            {
                v=t[i].y;
                if(dis[u]+t[i].c<dis[v])
                {
                    dis[v]=dis[u]+t[i].c;
                    if(if(!vis[v]))
                    {
                        r++;
                        q[r]=v;
                        vis[v]=true;
                    }
                }
            }
            r++;
        }
        return dis[n];
    }
    

    2.多源最短路径
    1.floyd

    void floyd()
    {
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(it j=1;j<=n;j++)
                    if(f[i][j]>f[i][k]+f[k][j])
                        f[i][j]=f[i][k]+f[k][j]
    }
    

    3.图的联通性问题

    1.无向图的最小环问题(floyd)

    代码

    #include <iostream>
    #include <cstring>
    #include <string>
    #include <cstdlib>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    int n,m,g[1001][1001],dis[1001][1001];
    int floyd()
    {
        int Mnin=999999999ll;
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<k;i++)
                for(int j=i+1;j<k;j++)
                    Mnin=min(Mnin,g[i][k]+g[j][k]+dis[i][j]);
            for(int i=1;i<=n;i++)
                for(int j=i;j<=n;j++)
                    dis[j][i]=dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        }
        return Mnin;
    }
    int main()
    {
        cin>>n>>m;
        int a,b,c;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        if(i==j)g[i][j]=dis[i][j]=0;
        else g[i][j]=dis[i][j]=999999999ll;
        for(int i=1;i<=m;i++)
        {
            cin>>a>>b>>c;
            g[a][b]=g[b][a]=dis[a][b]=dis[b][a]=c;
        }
    
        int v=floyd();
        if(v==999999999ll)cout<<"impossible"<<endl;
        else cout<<v<<endl;
        return 0;
    }
    

    2.欧拉回路

    1.判断

    1.对于无向图:

      存在欧拉回路的条件:每个点的度都为偶数;

      存在欧拉路的条件:有且只有两个点的度为一,且这两个点分别为起点和终点

    2.对于有向图:

      存在欧拉回路的条件:每个点出度等于入度;

      存在欧拉路的条件:存在一个点出度比入度多一作为起点,存在一点入度比出度多一作为终点,其余点出度等于入度;

    2.dfs搜索;

    在搜素的过程中,记录搜索次序;

    3.(Fleury)佛罗莱算法

    见博文(Fleury)佛罗莱算法;

    4.并查集

    代码

    int find(int x)
    {
        if(f[x]==x)return f[x];
        return f[x]=find(f[x]);
    }
    void together(int a,int b)
    {
        int aa=find(a),bb=find(b);
        f[aa]=f[bb];
    }
    

    5.最小生成树

    1.prim算法
    说明

    建立一棵树,每次加上这棵树的最近相邻接点,然后更新与新的树相邻的节点的距离,直到顶点都加入了树(可用优先队列优化);

    代码

    void prim()
    {
        memset(l,0x7ffff,sizeof(l));
        memset(vis,0,sizeof(vis));
        l[1]=0;
        for(int i=1;i<=n;i++)
        {
            int k=1;
            for(int j=1;j<=n;j++)
            if(!vis[j]&&l[k]>l[j])k=j;
            vis[k]=true;
            for(j=1;j<=n;j++)
                if(g[k][j]<l[j])l[j]=g[k][j];//g[k][j]---邻接矩阵;
        }
        int ans=0;
        for(int i=1;i<=n;i++)ans+=l[i];
        cout<<ans<<endl; 
    }
    

    kruskal

    1.把图中的边权值按从小到大的顺序排序;

    2.加上最短的边(边的两节点未连接,否则考虑下一条边【用并查集判断】);

    3.一共添加(n-1)条边;

    代码

    int find(int x)
    {
        if(f[x]==x)return f[x];
        return f[x]=find(f[x]);
    }
    void kruskal()
    {
        sort(t+1,t+n+1);
        for(int i=1;i<=n;i++)f[i]=i;
        for(int i=1;i<=n;i++)
            while(l<=nz)
            {
                l++;p=find(t[l].x);q=find(t[l].y);
                if(p!=q)
                {
                    Min=Min+t[i].w;
                    f[p]=q;
                    break;
                }
            }
    }
    

    6.拓扑排序

    将入度为0的点出栈;

    代码

    struct node
    {
        int y,nx,w; 
    }t[1000010];
    int q[110110],d[10010],head[10010];
    void top()
    {
        cin>>n>>p;
        int a,b,c,nz=0;
        for(int i=1;i<=p;i++)
        {
            cin>>a>>b>>c;
            t[++nz].y=b;t[nz].w=c;t[nz].nx=head[a];head[a]=nz;
            d[b]++;
        }
        int l=1,r=0;
        for(int i=1;i<=n;i++)
        if(d[i]==0){r++;q[r]=i;}
        while(l<=r)
        {
            int u=q[l];
            for(int i=head[u];i;i=t[i].nx)
            {
                int v=t[v].y;
                d[v]--;
                if(d[i]==0)
                {
                    r++;q[r]=v;
                }
            }
            l++;
        }
    }
    

    7.二分图(此处浅谈)

    1.二分图的染色

    核心思想:将一个图按照一定原则,进行黑白染色,若冲突,则不是二分图;

    原则例子1:(双栈排序)若a[i],a[j],a[k]满足i<j<k,且a[i]>a[k]而且a[i]<a[j],则a[j]进入第二个栈;

    2.二分图的最大匹配(匈牙利算法);

    代码

    bool dfs(int p)
    {
        for(int i=1;1<=n;i++)
        {
            if(Map[p][i]&&(!chk[i]))
            {
                chk[i]=true;
                if((match[i]==0)||dfs(match[i]))
                {
                    match[i]=p;return true;
                }
            }
        }
        return false;
    }
    void Hungary(int n)
    {
        int ans=0;
        for(int i=1;i=n;i++)
        {
            memset(chk,0,sizeof(chk));
            if(dfs(i))ans++;
        }
        cout<<ans<<endl;
    }
    
  • 相关阅读:
    mysql类似oracle rownum写法
    mysql派生查询必须有别名问题记录
    MySQL逻辑架构简介
    JSON转成List结构数据
    MySQL锁表查询SQL
    Http请求传json数据中文乱码问题
    异步调用导致的不同步问题
    oracle导入Excel表文本数据
    JSP页面的注释细节
    Oracle cursor学习笔记
  • 原文地址:https://www.cnblogs.com/lxyzlzj/p/13211825.html
Copyright © 2020-2023  润新知