zoukankan      html  css  js  c++  java
  • 备战快速复习--day13

    Bellman Ford

    进行n-1轮(最多n-1层,就是[0,n-2]),每次将所有的边松弛,如果进行之后还能松弛,说明是负环

    这个复杂度是O(VE),dijkstra是O(V^2+E)

    • 使用邻接表而不是邻接矩阵,邻接矩阵复杂度会上升
    • 邻接表在使用边的时候,判断好Adj[u][j]是对应的边,d[Adj[u][j].v]是对应边终点的d,中间距离dis是Adj[u][j].dis,这段容易搞错
    • 使用set要用insert,因为多轮松弛肯定会多次反复访问重复点,因此要用set
    • 在相等的时候,num的修改就是清零重新计算。(这个也导致不能存完pre等结束以后全部重新计算)
    • 初始num[st]=1;
    #include<stdio.h>
    #include<string.h>
    #include<set>
    #include<vector>
    using namespace std;
    int n,m,st,ed;
    const int INF=10000;
    int d[1000],w[1000],num[1000];//w代表累计,num是路径数
    set<int>pre[1000];
    int weight[1000]={0};
    struct Node{
        int v;
        int dis;
        Node(int tempv,int tempdis)
        {
            v=tempv;
            dis=tempdis;
        }
    };
    vector<Node>Adj[1000];
    void Bellman(int st)
    {
        fill(d,d+n,INF);
        memset(num,0,sizeof(num));
        for(int i=0;i<=n-1;i++)
            w[i]=weight[i];
        /*memset(w,0,sizeof(w));
        w[st]=weight[st];*/
        d[st]=0;
        num[st]=1;
        for(int i=0;i<n-1;i++)
        {
            for(int u=0;u<=n-1;u++)
            {
                for(int j=0;j<Adj[u].size();j++)
                {
                    int temp=Adj[u][j].v;
                    if(d[temp]>d[u]+Adj[u][j].dis)
                    {
                        pre[temp].clear();
                        pre[temp].insert(u);
                        w[temp]=w[u]+weight[temp];
                        d[temp]=d[u]+Adj[u][j].dis;
                    }
                    else if(d[temp]==d[u]+Adj[u][j].dis)
                    {
                        pre[temp].insert(u);
                        w[temp]=max(w[temp],(w[u]+weight[temp]));
                        set<int>::iterator it=pre[temp].begin();
                        num[temp]=0;
                        for(it=pre[temp].begin();it!=pre[temp].end();it++)
                        {
                            num[temp]+=num[*it];
                        }
                    }
                }
            }
        }
    }
    int main()
    {
        scanf("%d %d %d %d",&n,&m,&st,&ed);
        for(int i=0;i<=n-1;i++)
            scanf("%d",&weight[i]);
        for(int i=1;i<=m;i++)
        {
            int temp1,temp2,temp3;
            scanf("%d %d %d",&temp1,&temp2,&temp3);
            Adj[temp1].push_back(Node(temp2,temp3));
            Adj[temp2].push_back(Node(temp1,temp3));
        }
        Bellman(st);
        printf("%d %d",num[ed],w[ed]);
        return 0;
    }
    View Code

     A1003的代码。

    floyd是用来解决多源最短路,复杂度o3

    注意,这个本质上是贪心,在i-j的路径上有一堆点,每次通过一个点松弛,在松弛到最大点的时候,他的左边和右边都取到了最小值,那么他也是,往里推也一样,所以三层循环成立。

    每次选好点以后,对整个图松弛,所以选点在最外层。

    关于fill函数

    fill(a,a+n,INF)

    如果是二维数组fill(a[0],a[0]+maxn*maxn,INF)

    a[0]才是首地址

    fill在iostream头文件里面

    以有向图为例的floyd代码

    #include<stdio.h>
    #include<iostream>
    using namespace std;
    int n,m,G[100][100]={0};
    const int INF=10000;
    int main()
    {
        scanf("%d %d",&n,&m);
        fill(G[0],G[0]+100*100,INF);
        for(int i=1;i<=m;i++)
        {
            int temp1,temp2,temp3;
            scanf("%d %d %d",&temp1,&temp2,&temp3);
            G[temp1][temp2]=temp3;
            //G[temp2][temp1]=temp3;
        }
        for(int i=0;i<=n-1;i++)
            G[i][i]=0;
        for(int k=0;k<=n-1;k++)
        {
            for(int i=0;i<=n-1;i++)
            {
                for(int j=0;j<=n-1;j++)
                        G[i][j]=min(G[i][j],(G[i][k]+G[k][j]));
            }
        }
        for(int i=0;i<=n-1;i++)
        {
            for(int j=0;j<=n-1;j++)
            {
                printf("%d ",G[i][j]);
            }
            printf("
    ");
        }
        return 0;
    }
    View Code
    时间才能证明一切,选好了就尽力去做吧!
  • 相关阅读:
    Jaba_Web--JDBC 修改记录操作模板
    Jaba_Web--JDBC 查询记录操作模板
    Jaba_Web--JDBC 删除记录操作模板
    Java_Web--JDBC 增加记录操作模板
    C语言编程入门题目--No.15
    C语言编程入门题目--No.13
    C语言编程入门题目--No.14
    C语言编程入门题目--No.12
    C语言编程入门题目--No.10
    C语言编程入门题目--No.11
  • 原文地址:https://www.cnblogs.com/tingxilin/p/12483870.html
Copyright © 2011-2022 走看看