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

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

题目描述


明明同学被困在一个荒凉的北极岛屿,他可以用小船乘着海流用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("\n");
    }
    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("\n");
    }


以上便是对本题的相关阐述

目录
相关文章
|
7月前
|
机器学习/深度学习 监控 算法
【论文速递】CVPR2022-基于双重对比学习的非配对深度图像去噪
【论文速递】CVPR2022-基于双重对比学习的非配对深度图像去噪
|
2月前
|
人工智能 算法 BI
一篇带你速通差分算法(C/C++)
一篇带你速通差分算法(C/C++)
|
6月前
|
算法 C++
【c/c++算法】曼哈顿算法简单运用
【c/c++算法】曼哈顿算法简单运用
111 0
|
机器学习/深度学习
UPC - 2022春混合个人训练赛第五场 D Seahorse Shoes(贪心+模拟)
UPC - 2022春混合个人训练赛第五场 D Seahorse Shoes(贪心+模拟)
85 0
|
机器学习/深度学习 决策智能 计算机视觉
对硬币、销钉、大米进行图像分割(附代码)
对硬币、销钉、大米进行图像分割(附代码)
115 0
|
人工智能
upc 2021级新生个人训练赛第53场(珂朵莉与数字,珂朵莉与序列,珂朵莉与字符串,珂朵莉与面积)
upc 2021级新生个人训练赛第53场(珂朵莉与数字,珂朵莉与序列,珂朵莉与字符串,珂朵莉与面积)
95 0
|
机器学习/深度学习 存储 并行计算
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
神经辐射场去掉「神经」,训练速度提升100多倍,3D效果质量不减
161 0
|
人工智能
UPC——2020年春混合个人训练第二十四场(DEFG)
UPC——2020年春混合个人训练第二十四场(DEFG)
117 0
UPC——2020年春混合个人训练第二十四场(DEFG)
upc2021个人训练赛第22场A. 联通数(思维)
upc2021个人训练赛第22场A. 联通数(思维)
55 0
|
人工智能 定位技术 Go
UPC——2020年春混合个人训练第二十五场(FG)
UPC——2020年春混合个人训练第二十五场(FG)
96 0