• UPC训练第23场——寻路——弗洛伊德


    题目描述
    明明同学被困在一个荒凉的北极岛屿,他可以用小船乘着海流用1单位时间从一个岛移动到另一个岛。他得到了一个海洋地图,有N(1<=N<=100)条单向海流航线,编号为1…N。
    告诉你他的起始位置M(1<=M<=N)和地图,请编程帮助明明确定到达每个岛的最短时间是多少。
    输入为一个矩阵C,第r行,第c列的值若为1,则r到c存在海流,值为0则不存在海流。
    输入
    第1行:两个用空格隔开的整数:N和M
    第2…N+1:第i+1行包含N个用空格隔开的整数:C_R
    输出
    第1…??行:第一行输出M,第i+1行包含时刻i能到达的岛屿(升序排列)
    样例输入

    4 1 
    0 1 0 1 
    0 0 1 0 
    0 0 0 1 
    0 0 0 0
    

    样例输出

    1
    2 4
    3
    

    当时做这个题的时候,可以感觉出考点是弗洛伊德全源最短路问题,但是死活没明白样例是什么意思,于是乎卡了好像时间,先介绍一下题目的意思叭。

    给出的矩阵表达的意思是如果第 i 行,第 j 列是1,那么说明可以从 i 到达 j 。如果是0的话,那么就说明无法从 i 到 j 。 而给出的起点 m 可以看做是第几行的开始。拿样例来说,1,2为1,说明可以从1->2; 1,4为1,可以说明可以从1->4,两个需要的时间都是 1 。而要是从1->3 那么来说需要从1->2,2->3,两步来完成,耗时为2(样例第二行可以看出能够从2->3).
    输出情况就是先输出耗时短可以到达的岛屿,往下是耗时比较长的岛屿,如果好耗时相同,那么来说就需要从编号从小到大进行输出,比如耗时为1的可以从1到达的岛屿有24,先输出2,在输出4.
    一上来就看懂题的巨巨可以忽略以上的题目解释

    下面将附上本人的两种方法,两种方法都是可行的(根本都是一样的就只是用的vector方式不太一样罢了),但是之前一种方法因为一个条件把自己卡的死死的。伤心
    想要很好了解vector的小伙伴可以通过以下的链接来进行学习~~(巨佬请忽略)~~

    传送门1

    传送门2

    传送门3

    方法一

    #include <bits/stdc++.h>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    using namespace std;
    #define wuyt main
    typedef long long ll;
    #define HEAP(...) priority_queue<__VA_ARGS__ >
    #define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
    template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
    template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
    ///#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    ///char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
    ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
    if(c == '-')Nig = -1,c = getchar();
    while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
    return Nig*x;}
    #define read read()
    const ll inf = 1e15;
    const ll INF = 0x3f3f3f3f;
    const int maxn = 2e6 + 7;
    const int mod = 1e9 + 7;
    ll maxx=-1;
    ll minn=inf;
    ll num[1008];
    ll dis[1008][1008];
    ll num2[maxn];
    ll res,ans;
    map<string,ll> mp;
    priority_queue <int ,vector<int> ,greater<int> > xiaogen;
    bool cmp(ll a,ll b){
        return a>b;
    }
    queue <ll> duilie;
    queue <ll> cnt;
    vector <ll> vet;
    int main()
    {
        int n=read,m=read;
        for(int i=1;i<=n;i++){///初始化操作,将从自己到自己的时间设置成0
            for(int j=1;j<=n;j++){
                if(i==j) dis[i][j]=0;
                else dis[i][j]=mod;///其余设置成比较大的模数
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int a=read;
                if(a==0) continue;/// 如果是0那就说明两点不同就不再理会直接跳过
                else if(a==1) dis[i][j]=1;
            }
            dis[i][i]=0;///为了保险还是要将这里改成0,数据没问题应给可以不用加,但是本蒟蒻没有尝试
        }
        for(int k=1;k<=n;k++){/// 弗洛伊德三层for
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(dis[i][j]>dis[i][k]+dis[k][j])
                        dis[i][j]=dis[i][k]+dis[k][j];
                }
            }
        }
        /// 按照题目要求进行输出
        cout<<m<<endl;
        for(int i=1;i<=n;i++){
                ll temp=dis[m][i];
                num[i]=temp;
                if(temp==mod) temp=0;/// 划重点!91%卡在了这里
                vet.push_back(temp);
        }
        /// 排序去重
        sort(vet.begin(),vet.end());
        vet.erase(unique(vet.begin(),vet.end()),vet.end());
        int len=vet.size();/// 检测vector中存放了多少个数
        for(int i=1;i<=len-1;i++){
            for(int j=1;j<=n;j++){
                if(vet[i]==num[j]){///对应相等输出对应的编号
                    printf("%d ",j);
                }
            }
            puts("");
        }
        return 0;
    }
    
    

    warning

      for(int i=1;i<=n;i++){
                ll temp=dis[m][i];
                num[i]=temp;
                if(temp==mod) temp=0;/// 划重点!91%卡在了这里
                vet.push_back(temp);
        }
    

    在这里如果两点行不通的情况下不排除,将会卡在91%,亲测有效
    在这里本蒟蒻优化了一下,将行不通的情况那个临时变量temp 变成0,这样一来就会将和自身到自身的那个0在后面去重掉,将不影响最终结果

    方法2

    #include <bits/stdc++.h>
    #include <algorithm>
    #include <map>
    #include <queue>
    #include <set>
    #include <stack>
    #include <string>
    #include <vector>
    using namespace std;
    #define wuyt main
    typedef long long ll;
    #define HEAP(...) priority_queue<__VA_ARGS__ >
    #define heap(...) priority_queue<__VA_ARGS__,vector<__VA_ARGS__ >,greater<__VA_ARGS__ > >
    template<class T> inline T min(T &x,const T &y){return x>y?y:x;}
    template<class T> inline T max(T &x,const T &y){return x<y?y:x;}
    ///#define getchar()(p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    ///char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
    ll read(){ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar();
    if(c == '-')Nig = -1,c = getchar();
    while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar();
    return Nig*x;}
    #define read read()
    const ll inf = 1e15;
    const ll INF = 0x3f3f3f3f;
    const int maxn = 2e6 + 7;
    const int mod = 1e9 + 7;
    ll maxx=-1;
    ll minn=inf;
    ll num[1008];
    ll dis[1008][1008];
    ll num2[maxn];
    ll res,ans;
    map<string,ll> mp;
    priority_queue <int ,vector<int> ,greater<int> > xiaogen;
    bool cmp(ll a,ll b){
        return a>b;
    }
    queue <ll> duilie;
    queue <ll> cnt;
    vector <ll> vet[maxn];
    int main()
    {
        int n=read,m=read;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j) dis[i][j]=0;
                else dis[i][j]=mod;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                int a=read;
                if(a==0) continue;
                else if(a==1&&i!=j) dis[i][j]=1;
            }
            dis[i][i]=0;
        }
        for(int k=1;k<=n;k++){
            for(int i=1;i<=n;i++){
                for(int j=1;j<=n;j++){
                    if(dis[i][j]>dis[i][k]+dis[k][j])
                        dis[i][j]=dis[i][k]+dis[k][j];
                }
            }
        }
        cout<<m<<endl;
        for(int i=1;i<=n;i++){
            if(i!=m&&dis[m][i]!=mod){
                ll temp=dis[m][i];
                maxx=max(maxx,temp);
                vet[temp].push_back(i);
            }
        }
        for(int i=1;i<=maxx;i++){
            for(auto tmp:vet[i]) cout<<tmp<<" ";
            printf("
    ");
        }
        return 0;
    }
    
    

    和第一种方式不同的只有这一点,但是第一次使用这种方式过的,不容易忘记条件,但是说实话,本蒟蒻驾驭不了这种使用vector的方式,看的到这种方法真的是眼前一亮

    	/// 前面声明的时候一定要记得加上想要申请的vector的大小
    	/// 例如: vector <ll> vet[maxn];
        cout<<m<<endl;
        for(int i=1;i<=n;i++){
            if(i!=m&&dis[m][i]!=mod){
                ll temp=dis[m][i];
                maxx=max(maxx,temp);
                vet[temp].push_back(i);
            }
        }
        for(int i=1;i<=maxx;i++){
            for(auto tmp:vet[i]) cout<<tmp<<" ";
            printf("
    ");
        }
    

    以上便是对本题的相关阐述
    点个赞再走嘛

  • 相关阅读:
    html5基础---canvas
    html5基础---h5特性
    JS常用知识点(一)
    微信小程序开发(一)基础知识学习
    关于C# winform唤起本地已安装应用程序(测试win10,win7可用)
    js原型链结构理解
    JS闭包应用场景之函数回调(含函数的调用个人理解)
    (十三)MySQL锁机制
    (十一)MVCC-多版本并发控制机制(转)
    jvm014-垃圾回收器
  • 原文地址:https://www.cnblogs.com/PushyTao/p/13144150.html
Copyright © 2020-2023  润新知