ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

日更计划Day3 CSP-J2019第四题

2021-03-11 13:01:23  阅读:181  来源: 互联网

标签:Map return int Day3 num push J2019 odd CSP


题目描述

有一个无向图,一号节点为0,无限更新相邻节点,每次更新为相邻节点编号加一。共有q次询问,分别询问对于i点是否更新过pi值。[题目传送门](http://hzjingma.com/?#/problem/6003)

错误思路分析

一开始看到这题时,我以为将所有节点用BFS更新一次,然后询问你找到所有相邻节点看看包含的最小奇数和偶数是否能够满足询问的数字。但是没有仔细看第二个例子,发现询问1,5时,我的程序并不会从1绕一圈跑回来因此得到5这个答案,所以这个办法行不通。

//错误思路代码
#include<bits/stdc++.h>
//#include "stdc++.h"
//#define int long long
using namespace std;
const int N = 1e5+5;
const int INF = 1e9;
int n,m,q,a,b,p,num;
int vis[N];
int ans[N];
struct node{
    int step;
};
vector<int>Map[N];
void BFS(int st){
    vis[st] = 1;
    ans[st] = 0;
    queue<int>q;
    q.push(st);
    while (q.size()) {
        int fr = q.front();
        q.pop();
        for (int i = 0; i < Map[fr].size(); i++){
            int v = Map[fr][i];     //说明fr与v之间有一条连线
            if (vis[v] != 0) continue;      //防止重复
            ans[v] = ans[fr]+1;
            vis[v] = 1;
            q.push(v);
        }
    }
}
string search(int p, int num){
    int MinE = INF;
    int MinO = INF;
    for (int i = 0; i < Map[p].size(); i++){
        int pos = Map[p][i];
        int app = ans[pos];
        if (app % 2 == 0){
            MinE = min(MinE,app);
        }else{
            MinO = min(MinO,app);
        }
    }
    cout << MinE << " " << MinO << endl;
    if(MinO == INF && num % 2 == 0){
        return "No\n";
    }
    if (MinE == INF && num % 2 != 0) return "No\n";
    if (num % 2 == 0){
        if (num >= MinO+1) return "Yes\n";
        if(MinO == INF) return "No\n";
    }else{
        if (num >= MinE+1) return "Yes\n";
        if (MinE == INF) return "No\n";
    }
    
    return "No\n";
}
int main(){
    cin >> n >> m >> q;
    for (int i = 1; i <= m; i++){
        cin >> a >> b;
        Map[a].push_back(b);
        Map[b].push_back(a);
    }
    BFS(1);
    for (int i = 1; i <= q; i++){
        cin >> p >> num;
        cout << search(p,num);
    }
    return 0;
}

正解思路

由于我们不知道从1到其他点是否能有奇数和偶数的解,但是和之前的错误思路相同,我们知道一个点只要能在5步到达就必然能够在7步到达(走出一步再走回来),然而最小到达步数是5的话,小于5的奇数步都不能够到达。于是,我们应该由1到所有点求一边奇数最短路以及偶数最短路。这里采用SPFA算法(参考落谷第一篇题解)。

#include<bits/stdc++.h>
//#include "stdc++.h"
//#define int long long
using namespace std;
const int N = 1e5+10;
int n,m,q,a,b,x,y,dist[N],odd[N],even[N];
vector<int>Map[N];
void SPFA(int u){
    queue<pair<int, int> >q;
    memset(odd, 0x3f, sizeof(odd));
    memset(even, 0x3f, sizeof(even));
    for (int i = 0; i < Map[1].size(); i++){
        odd[Map[1][i]] = 1;                 //连着1的最短奇数边都是1
        q.push(make_pair(Map[1][i], 1));
    }
    while (q.size()) {
        int p = q.front().first;
        int num = q.front().second;
        q.pop();
        for (int i = 0; i < Map[p].size(); i++){
            if (num % 2 == 0){
                //是偶数的话,更新奇数最短路(因为要走一步到当前枚举的点)
                if(num+1 < odd[Map[p][i]]){
                    odd[Map[p][i]] = num+1;
                    q.push(make_pair(Map[p][i], num+1));
                }
            }else{
                //是奇数的话,更新偶数最短路
                if(num+1 < even[Map[p][i]]){
                    even[Map[p][i]] = num+1;
                    q.push(make_pair(Map[p][i], num+1));
                }
            }
        }
    }
}
int main(){
    cin >> n >> m >> q;
    for (int i = 1; i <= m; i++) {
//        cin >> a >> b;
        scanf("%d %d", &a,&b);
        Map[a].push_back(b);
        Map[b].push_back(a);
    }
    SPFA(1);
    for (int i = 1; i <= q; i++){
//        cin >> x >> y;
        scanf("%d %d",&x,&y);
        if (y % 2 == 0){
            if (even[x] > y) printf("No\n");
            else printf("Yes\n");
        }else {
            if (odd[x] > y) printf("No\n");
            else printf("Yes\n");
        }
    }
    return 0;
}

总结

需要熟练运用最短路的几个模版,并且思考的更全面一些。

标签:Map,return,int,Day3,num,push,J2019,odd,CSP
来源: https://blog.csdn.net/weixin_46671186/article/details/114660339

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有