• 第三节暑期信息奥赛课——图论


    2019-07-08 16:02:00

    第三节暑期信息奥赛课——图论

    绪言

    图论这东西,纠缠我很久啦!我接触的第一道图论题是2017普及组D1T3 洛谷P3956 棋盘(dijkstra算法)

    当时用暴力法,整了个不到50分,但是还是不会这个算法。

    图论乃是NOIP的重点之一!


     最短路径问题


    ----Floyd

    时间复杂度O(n^3)

    只有五行!!!死也要给我背下来!!!

    #include<iostream>
    //#include<cstring>
    using namespace std;
    int main(){
        int num,way;
        cin>>num>>way;
        int sz[num+1][num+1];
        int tx,ty,tz;
        for(int n=1;n<=num;n++)
        for(int m=1;m<=num;m++)
            sz[n][m]=0xFFF;
        //memset(sz,0x3F,sizeof(sz);
        for(int n=1;n<=way;n++)
        {
            cin>>tx>>ty>>tz;
            sz[tx][ty]=min(sz[tx][ty],tz);//陷阱一:可能有重复输入两点距离 
        }
        
        for(int i=1;i<=num;i++)
            sz[i][i]=0;//自己到自己的距离是0 
        //核心代码 
        for(int k=1;k<=num;k++){//k一定是在最外层,在动规中是状态 
            for(int i=1;i<=num;i++)
            for(int j=1;j<=num;j++){
            if(sz[i][j] > sz[i][k]+sz[k][j]);//寻找桥梁点k,会使得i to k&k to j比i to j更短 
                sz[i][j] = sz[i][k]+sz[k][j];
            }
        }
        
        for(int i=0;i<num;i++){
            for(int j=0;j<num;j++)
                cout<<sz[i][j]<<" ";
            cout<<endl;
            }
        return 0;
    } 

    ----Dijkstra

    基础版的O(n^2),代码稍长

    可优化

    #include<iostream>
    #include<cstring>
    using namespace std;
    const int MAXN=0x3F,inf=0x3F3F3F;
    int num,way,minNum,minIndex;
    int sz[MAXN][MAXN];
    int dis[MAXN];
    bool vis[MAXN];
    void dij(int s){
        memset(dis,1,sizeof(dis));
        memset(vis,1,sizeof(vis));
        for(int p=1;p<=num;p++)
            dis[p]=sz[s][p];
        vis[s]=1;
        
        for(int j=1;j<=num;j++){
            int minIndex=1,minNum=inf+1;
            for(int i=1;i<=num;i++)
                if(vis[i]==1 && dis[i]<minNum){
                    minNum=dis[i];
                    minIndex=i;
                }
        } 
        
        vis[minIndex]=1;
        for(int i=1;i<=num;i++)
            if(vis[i]==1 && dis[i]>dis[minIndex]+sz[minNum][i]){
                dis[i]==dis[minIndex]+sz[minNum][i];
            }
    }
    int main(){
        cin>>num>>way;
        int tx,ty,tz;
        //初始化 
        for(int n=1;n<=num;n++)
        for(int m=1;m<=num;m++)
            sz[n][m]=MAXN;
        //msmset(sz,0x3F,sizeof(sz);
        for(int n=1;n<=way;n++)
        {
            cin>>tx>>ty>>tz;
            sz[tx][ty]=min(sz[tx][ty],tz);//陷阱一:可能有重复输入两点距离 
        }
        dij(1);
        for(int i=1;i<=num;i++){
            for(int j=1;j<=num;j++)
                cout<<sz[i][j]<<" ";
            cout<<endl;
            }
        return 0;
    } 
    /*
    1、把sz[1][j]搬到一个一维数组dis中(起点到其他所有点的距离) 
    2、松弛操作:从dis中找一个没用过,且最小的点
    3、 
    */

    最小生成树问题


    ----kruskal

    要用到并查集哟(^U^)ノ~YO

    #include<iostream>
    using namespace std;
    int n,m;
    const int MAXN=0x3F3F3F;
    int f[MAXN];
    //并查集开始 
    int init(){//初始化 
        for(int i=1;i<=n;i++)
            f[i]=i;
    } 
    
    int getf(int i){
        if(i==f[i]) return i;//没有祖先,或者说就是它自己 
        else return f[i]=getf(f[i]);//有祖先,就把f[i]也变成即将查找到的它的祖先的祖先,状态压缩 
    }
    
    void merge(int a,int b ){
        int x=getf(a);
        int y=getf(b);
        
        if(x!=y) f[x]=f[y];
    }    
    int main(){
        int a,b,c;
        cin>>n>>m;
        init(); //初始化
        for(int i=1;i<=m;i++)
            cin>>a>>f[a];
        
            
        return 0;
    } 
     
    /*
    kruskal算法 
    1、清除所有边
    2、找两点使得距离最短,连线
    3、用并查集判断有没有环(回路)
    4、 
    */ 
    /*
    并查集
    对一个集合进行合并,查找
    1、把一个一维数组sz的值初始化为其下标
    2、若A与B有关系,则sz[A]=B;
    3、若A与C有关系 
    最后,有多少个下标仍是值的数值,就有 
    */ 
    kruskal

    代码的输入有问题,记得修复!


    ----Prim

    (未完待续......)

    以后做到了再说吧。。。

  • 相关阅读:
    codevs 1792 分解质因数
    ScrollView嵌套ViewPager,ViewPager内容不显示问题
    AndroidStudio不重新运行,Debug调试已有进程
    Android进阶之Fragment与Activity之间的数据交互
    Android修改包名的方法,简单粗暴。
    android studio 按钮运行按钮后,不弹出选择运行模拟器的对话框
    RGB颜色值与十六进制颜色码转换工具
    Android Studio查看其它APP的布局结构
    android实现多条件筛选列表菜单筛选菜单
    Android,一条线串联实心圆布局
  • 原文地址:https://www.cnblogs.com/send-off-a-friend/p/11138181.html
Copyright © 2020-2023  润新知