• 图论基础知识.


      今天先写一些基础的图论知识;

    1.floyed算法;

    2.spfa算法;
     
    3.dijkstra(迪杰斯特拉)算法;(先不写)

    1.floyed算法

    可以找到任意两点之间的最短路,即dis[i][j];

    原理:图的传递闭包思想;时间复杂度:O(n*n*n);
     思想也比较好理解(三角形任意两边之和大于第三边嘛,如果出现不符合,就更新距离,这样比较好想)


    例题oj1212
    图G是一个无向连通图,没有自环,并且两点之间至多只有一条边。我们定义顶点v,u最短路径就是从v到u经过边最少的路径。所有包含在v-u的最短路径上的顶点被称为v-u的Geodetic顶点,这些顶点的集合记作I(v, u)。
    我们称集合I(v, u)为一个Geodetic集合。
    例如下图中,I(2, 5)={2, 3, 4, 5},I(1, 5)={1, 3, 5},I(2, 4)={2, 4}。



    给定一个图G和若干点对v,u,请你分别求出I(v, u)。
    输入:
     第一行两个整数n,m,分别表示图G的顶点数和边数(顶点编号1-n)
      下接m行,每行两个整数a,b表示顶点a和b之间有一条无向边。
      第m+2行有一个整数k,表示给定的点对数。
      下接k行,每行两个整数v,u。
    输出:
    共k行,每行对应输入文件中每一个点对v,u,按顶点编号升序输出I(v, u)。同一行的每个数之间用空格分隔。

    思想:就是跑一个floyed,记录所经过的每一个点再输出就好了吧
    原来看书 好像可以做一个p[i][j]数组用来储存所经过的点..
    但是我做这个题的时候还不会,所以先跑了一个floyed,最后寻找如果i到k再到j的距离等于i到j的最短路,那不是很明显他在最短路上嘛,记录一个每一个k,最后输出就好这样操作比较简单;
    存图用邻接矩阵就好了
    #include<bits/stdc++.h>
    using namespace std;
    int dis[1500][1500],a[1500],n,m,t,f[1500][1500],xx,yy;
    inline int read()
    {
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    inline void dfs()
    {
        for(int k=1;k<=n;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    if(dis[i][k]+dis[k][j]<=dis[i][j]) 
                    {
                        dis[i][j]=dis[i][k]+dis[k][j];
                    }
                }
    }
    int main()
    {
        memset(dis,10,sizeof(dis));
        m=read();n=read();
        for(int i=1;i<=n;i++)
        {
            cin>>xx>>yy;
            dis[xx][yy]=1;
            dis[yy][xx]=1;
        }
    //    cout<<dis[4][5]<<endl;
        dfs();
        t=read();
        int x,y;
    
        for(int i=1;i<=t;i++)
        {
            x=read();y=read();
            int s=0;
            a[++s]=x;
            for(int j=1;j<=n;j++)
            {
                if(dis[x][j]+dis[j][y]==dis[x][y])
                a[++s]=j;
            }
            //cout<<dis[2][4]<<' '<<dis[4][5]<<endl; 
            a[++s]=y;
            sort(a+1,a+s+1);
            for(int j=1;j<=s;j++)
            { 
                cout<<a[j]<<' ';
            }
            cout<<endl;
        } 
        return 0;
    }

    2.spfa算法
    关于spfa,当初听课的时候学长讲:关于spfa,它死了..
    用栈来模拟,每次取出对头,判断是否需要更新,用dis数组存到任意一点的最短距离;
    oj1215
    农夫John发现做出全威斯康辛州最甜的黄油的方法:糖。把糖放在一片牧场上,他知道N(1<=N<=500)只奶牛会过来舔它,这样就能做出能卖好价钱的超甜黄油。当然,他将付出额外的费用在奶牛上。 
    农夫John很狡猾。像以前的Pavlov,他知道他可以训练这些奶牛,让它们在听到铃声时去一个特定的牧场。他打算将糖放在那里然后下午发出铃声,以至他可以在晚上挤奶。 
    农夫John知道每只奶牛都在各自喜欢的牧场(一个牧场不一定只有一头牛)。给出各头牛在的牧场和牧场间的路线,找出使所有牛到达的路程和最短的牧场(他将把糖放在那) 
    输入:
    第一行: 三个数:奶牛数N,牧场数(2<=P<=800),牧场间道路数C(1<=C<=1450) 
    第二行到第N+1行: 1到N头奶牛所在的牧场号 
    第N+2行到第N+C+1行: 每行有三个数:相连的牧场A、B,两牧场间距离(1<=D<=255),当然,连接是双向的 
    输出:一行 输出奶牛必须行走的最小的距离和
     
    #include<bits/stdc++.h>
    using namespace std;
    #define N 1500
    int lin[N],tot;
    int n,m,h,w[N],vis[N],dis[N],d[N];
    int xx,yy,zz;
    long long minn=100100000000000ll,ans=0;
    struct gg
    {
        int x,y,v;
        int next;
    }a[N<<1];
    inline void init(int xx,int yy,int vv)
    {
        a[++tot].y=yy;
        a[tot].next=lin[xx];
        a[tot].v=vv;
        lin[xx]=tot;
    }
    inline void spfa(int s)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,257,sizeof(dis));
        queue<int> q;
        dis[s]=0;vis[s]=1;q.push(s);
        while(q.size())
        {
            int x=q.front();q.pop();
            for(int i=lin[x];i;i=a[i].next)
            {
                int v=a[i].y;
                if(dis[v]>dis[x]+a[i].v)
                {
                    dis[v]=dis[x]+a[i].v;
                    if(!vis[v])    vis[v]=1,q.push(v);
                }
            }
            vis[x]=0;
        }
    }
    int main()
    {
        cin>>n>>m>>h;
        for(int i=1;i<=n;i++)
            cin>>d[i];
        for(int i=1;i<=h;i++)
        {
            cin>>xx>>yy>>zz;
            init(xx,yy,zz);
            init(yy,xx,zz);
        }
        for(int i=1;i<=m;i++)
        {
            spfa(i);ans=0;
            for(int  j=1;j<=n;j++)
                ans+=dis[d[j]];
            if(ans<minn) minn=ans;
        }
        cout<<minn;
        return 0;
    }

  • 相关阅读:
    【好文收藏】家庭
    CSS选择器
    高等数学
    生也有涯而知也无涯,以有涯应无涯,殆矣
    navicat连接MySQL8+时出现2059错误解决方法
    Python 自己常用的方法
    Vue中变量名前加三个点代表什么意思
    Python3 locals函数的妙用
    python元类的应用
    vue + Element UI 之 rules校验
  • 原文地址:https://www.cnblogs.com/Tyouchie/p/10204573.html
Copyright © 2020-2023  润新知