zoukankan      html  css  js  c++  java
  • 图论最短路——spfa

    今天开始图论的最短路的最后复习,今天自己手打spfa虽然看了一眼书,但是也算是自己打出来的,毕竟很久没打了,而且还是一遍a代码下来15min左右就搞完了,成就感++。所以呢来篇博客记录一下。

    香甜的黄油,当年做的时候吃了不少苦头现在完全会打了,下面是当时我的代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cmath>
    #include<ctime>
    #include<iostream>
    #include<string>
    using namespace std;
    const int maxn=1002,inf=1000000000;
    int n,p,c,a,b,d,t,dist[maxn],s1[maxn],inq[maxn];
    vector<int>g[maxn],w[maxn];
            
    void spfa(int s)
    {
        queue<int>a;//一个队列a
        for(int i=1;i<=p;i++)//循环4个牧场都附极大值
        dist[i]=inf;
        memset(inq,0,sizeof(inq));//清空inp
    
        dist[s]=0;//把到当前的牧场距离设为0,毕竟是自己到自己
        a.push(s);//进队
        inq[s]=1;//使其为1
    
        while(!a.empty())//如果队列不为空
        {
            int i=a.front();//返回队首元素
            a.pop();//弹出队首
            inq[i]=0;//使其为0
            for(int k=0;k<g[i].size();k++)//当前的牧场和其余的牧场相连
            {
                int j=g[i][k];//取i到j的牧场号询问其距离
                if(dist[i]+w[i][k]<dist[j])//如果当前距离和i到k的距离小于j松弛操作
                {
                    dist[j]=dist[i]+w[i][k];//松弛
                    if(inq[j]!=0) continue;//询问是否在队列之中
                    inq[j]=1;//不在的话再次标记
                    a.push(j);//使当前的点进队好像bfs但不是bfs多次进队
                }
            }
        }
    }
    
    int main()
    {
        //freopen("1.in","r",stdin);
        scanf("%d%d%d",&n,&p,&c);//n为奶牛所在的牧场号,p为4个牧场,c为5个牧场的关系
        memset(s1,0,sizeof(s1));//s1存的是奶牛的牧场位置;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&t);//
            s1[t]++;//牧场
        }
        for(int i=1;i<=c;i++)
        {
            scanf("%d%d%d",&a,&b,&d);//a与b之间的距离为d
            g[a].push_back(b);//扩边
            g[b].push_back(a);
            w[a].push_back(d);//二次扩边
            w[b].push_back(d);
        }
        int ans=inf;//附最大值
        for(int i=1;i<=p;i++)//枚举每一个牧场为起点
        {
            spfa(i);//当黄油放在第i个牧场时来一个一个判断;跑距离
            int sum=0;
            for(int j=1;j<=p;j++)
            {     
                if(!s1[j]) continue; 
                sum+=dist[j]*s1[j]; //计算奶牛到牧场的距离和
            }
            ans=min(sum,ans); //取最小值
        }
        printf("%d",ans);
        return 0;
    }
    View Code

    注释很多很多,主要因为当时的不理解。

    下面是本人今天的代码!!!

    #include<iostream>
    #include<cstring>
    #include<string>
    #include<cstdio>
    #include<cmath>
    #include<iomanip>
    #include<algorithm>
    #include<stack>
    #include<ctime>
    #include<vector>
    #include<queue>
    #include<map>
    #define inf 10000000
    using namespace std;
    const int maxn=5000;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int b[maxn],ver[maxn],lin[maxn],nex[maxn],len=0,e[maxn],minn=inf,dis[maxn],q[maxn];
    bool vis[maxn];
    void add(int x,int y,int z)
    {
        ver[++len]=y;
        nex[len]=lin[x];
        lin[x]=len;
        e[len]=z;
    }
    int n,m,k,h,t;
    void spfa(int x)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,10,sizeof(dis));
        memset(q,0,sizeof(q));
        dis[x]=0;vis[x]=1;q[1]=x;
        h=0,t=1;
        while(h<=t)
        {
            int tn=q[++h];vis[tn]=0;
            for(int i=lin[tn];i;i=nex[i])
            {
                int tmp=ver[i];
                if(dis[tn]+e[i]<dis[tmp])
                {
                    dis[tmp]=dis[tn]+e[i];
                    if(vis[tmp]!=1)
                    {
                        q[++t]=tmp;
                        vis[tmp]=1;
                    }
                }
            }
        }
    }
    int main()
    {
        freopen("1.in","r",stdin);
        k=read();m=read();n=read();
        memset(b,0,sizeof(b));
        for(int i=1;i<=k;i++){int x;x=read();b[x]++;}
        for(int i=1;i<=n;i++)
        {
            int x,y,z;
            x=read();y=read();z=read();
            add(x,y,z);
            add(y,x,z);
        }
        for(int i=1;i<=m;i++)
        {
            int ans=0;
            spfa(i);
            for(int j=1;j<=m;j++)
            {
                if(b[j]!=0)
                    ans+=dis[j]*b[j];
            }
            minn=min(ans,minn);
        }
        printf("%d
    ",minn);
        return 0;
    }
    View Code

    思路很清晰的打完了哈哈。

    莫听穿林打叶声,何妨吟啸且徐行。

  • 相关阅读:
    django文件上传
    django验证码
    auth模块---笔记
    css笔记
    django模板系统---2
    django模板系统
    Django中间件
    前端笔记---1
    我的django笔记---1
    DNS服务器的搭建
  • 原文地址:https://www.cnblogs.com/chdy/p/9700429.html
Copyright © 2011-2022 走看看