• mathematical method


    mathematical method

    曲线拟合

    • 指数 (lnY = lna + bX)
    • 对数 (Y = blnX + a)
    • 幂函数 (lgY=lga+blgX)

    多元线性回归模型

    • 回归分析中有两个或者两个以上的自变量,就是多元回归
    • 最小化残差平方和 SSE

    图论: Floyd

    #include <iostream>
    
    using namespace std;
    
    const int maxn = 200;
    
    int n,s,t;
    int a[maxn+1][maxn+1];
    
    void init()
    {
        int m,u,v;
        cin >> n >> m;
        for(int i =1; i<=n; i++)
            for(int j =1; j<=n; j++)
                a[i][j] = -1;
        for(int i = 1; i<=m; i++)
            cin >> u >> v >> a[u][v];
        cin >> s >> t;
    }
    
    
    void floyd()
    {
        int i,j,k;
        for(k=1; k<=n; k++)
            for(i=1; i<=n; i++)
                for(j=1; j<=n; j++)
                {
                    if(a[i][k]!=-1&&a[k][j]!=-1)
                        a[i][j] = min(a[i][j],a[i][k]+a[k][j]);
                }
    }
    
    int main()
    {
        init();
        floyd();
        cout << a[s][t]+a[t][s]<<endl;
        return 0;
    }
    

    图论: Prim 算法

    • 解决最小生成树问题
    • 采用的方法是加点法
    • 在所有加过的点中找到距离其他点最短路径的点&&不能构成回路,加入集合,
    //这里使用无向图
    #include <iostream>
    
    using namespace std;
    
    const int MAXN = 2001;
    const int INF = 99999999;
    
    int n,e;
    int w[MAXN][MAXN];
    int mincount[MAXN]; //从初始顶点到该顶点的最小权值
    
    
    void init()
    {
        int i,j;
        int tx,ty;
        for(i = 0; i<=MAXN; i++)
            for(j =0; j<MAXN; j++)
                w[i][j] = INF;
    
        cin >> n >> e;
    
        for(i = 1; i<=e; i++)
        {
            cin >> tx >> ty >> w[tx][ty];
            w[ty][tx] = w[tx][ty];
        }
    }
    
    void prim(int s)   //从标号为s处开始生成树
    {
        int i,j,cnt = 0,min; // cnt 是生成树所有边的权值之和
        int k;
        for(i = 1; i<= n; i++)
            mincount[i] = w[s][i]; //  初始化,设w[1][i]是初始点k到i的最小权值,如果没有就设为INF
        mincount[s] = 0;
    
        for(i = 1; i < n; i++) //一共有n-1次
        {
            min = INF;
            for(j = 1; j <= n; j++)
            {
                if(mincount[j]!=0 && mincount[j]<min)
                {
                    min = mincount[j];
                    k = j;        //记录该点
                }
                mincount[k] = 0;//将该点加入到最小生成树中
                cnt += min;   //将这条边权值加入到最小生成树中
    
                for(j = 1;j<=n;j++)  //修正初始点到每个点的最小权值
                {
                      if(w[k][j]<mincount[j])
                            mincount[j] = w[k][j];
                }
            }
        }
        cout << cnt << endl;
    }
    
    int main()
    {
        init();
        prim(1);
        return 0;
    }
    
    

    图论: Kruskal算法 - 加边法

    • 主要用到的是并查集
    #include <iostream>
    
    using namespace std;
    
    const int MAXN = 2000;
    const int INF = 99999999;
    int n,e;// n是点的数量,e是边的数量
    int x[MAXN],y[MAXN],w[MAXN];
    int parent[MAXN];
    
    int Find(int x)
    {
        if(parent[x] == x)
            return x;
        else
            return parent[x] = Find(parent[x]);
    }
    
    
    void Merge(int a,int b)
    {
        int pa = Find(a);
        int pb = Find(b);
        if(pb < pa)
            swap(pb,pa);
        if(pa!=pb)
            parent[pa] = pb;
    }
    
    
    void kruskal()
    {
        int i,p,ans;  //p是已经加入的边数,ans是加入边的边权之和
    
        for(i = 1; i<=n ; i++) //initialize
        {
            parent[i] = i;
        }
    
        p = 1;
        ans = 0;
    
        for(i = 1; i <= e; i++)
        {
            if(Find(x[i])!=Find(y[i]))// 两点没有在同一个集合中,归并两个集合
            {
                ans += w[i];
                Merge(x[i],y[i]);
                p++;
                if(p == n)    //这里不是n-1,因为初始化的时候,p = 1
                {
                    cout << ans << endl;
                    return;
                }
            }
        }
        return;
    }
    
    
    void sort(int i, int j)
    {
        if(i >=j)
            return;
        int m,n,k;
        m = i;
        n = j;
        k = w[(i+j)>>1];
        while(m <= n)
        {
            while(w[m]<k)
                m++;
            while(w[n]>k)
                n--;
            if(m <= n)
            {
                swap(x[m],x[n]);
                swap(y[m],y[n]);
                swap(w[m],w[n]);
                m++;
                n--;
            }
        }
        sort(i,n);
        sort(m,j);
    }
    
    
    int main()
    {
        int i,j;
        cin >> n >> e;
        for(i = 1; i <= e ; i++)
        {
            cin >> x[i] >> y[i] >> w[i];
        }
        sort(1,e);
        kruskal();
        return 0;
    }
    

    最大流 - Ford fulkerson算法

    残余网络 & 增广路径

    Ford-Fulkerson方法的正确性依赖于这个定理:当残存网络中不存在一条从s到t的增广路径,那么该图已经达到最大流。

    伪代码

    Ford-Fulkerson
        for <u,v> ∈ E
            <u,v>.f = 0
        while find a route from s to t in e
                m = min(<u,v>.f, <u,v>  ∈ route)
            for <u,v> ∈ route
                if <u,v>  ∈ f
                    <u,v>.f = <u,v>.f + m
                else
                    <v,u>.f = <v,u>.f - m
    

    实现过程中的重点自傲与如何寻找增广路径

    • 可以使用广度搜索
    • 可以用Bellmanford算法进行计算
    • 残存网络就是在流网络的基础上改变的,容量仍然保持不变,只改变已经用过的容量.将其反向如果流量为0那就不用再表示在图上了
    #include<stdio.h>
    #include<stdlib.h>
    #include<vector>
    #include<algorithm>
    
    #define MAXVEX 100
    #define INF 65535
    
    //用于表示边的结构体
    struct edge
    {
        int to;//终点
        int cap;//容量
        int rev;//反向边
    };
    std::vector<edge>G[MAXVEX];//图的邻接表表示
    bool used[MAXVEX];//DFS中用到的访问标记
    
    //向图中增加一条从s到t容量为cap的边
    void addEdge(int from, int to, int cap)
    {
        edge e;
        e.cap = cap;e.to = to;e.rev = G[to].size();
        G[from].push_back(e);
        e.to = from; e.cap = 0; e.rev = G[from].size() - 1;
        G[to].push_back(e);
    }
    
    //通过DFS寻找增广路
    int dfs(int v, int t, int f)
    {
        if (v == t)return f;
        used[v] = true;
        for (int i = 0; i < G[v].size(); ++i)
        {
            edge &e = G[v][i];
            if (!used[e.to] && e.cap > 0)
            {
                int d = dfs(e.to, t, std::min(f, e.cap));
                if (d > 0){
                    e.cap -= d;
                    G[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }
        return 0;
    }
    
    //求解从s到t的最大流
    int max_flow(int s, int t)
    {
        int flow = 0;
        for (;;)
        {
            memset(used, 0, sizeof(used));
            int f = dfs(s, t, INF);
            if (f == 0)return flow;
            flow += f;
        }
    }
    
  • 相关阅读:
    favicon.ico请求处理
    Node.js学习(Node.js基础)
    实现主机访问虚拟机网页的方法总结
    有向/无向图中搜环
    后缀自动机
    莫队算法
    A* 算法求第k短路径
    次小生成树算法
    AC自动机详解
    Link-Cut-Tree详解
  • 原文地址:https://www.cnblogs.com/pprp/p/8411268.html
Copyright © 2020-2023  润新知