题解:ABC320D - Relative Position

题解:ABC320D - Relative Position

·题目

链接:Atcoder。

链接:洛谷。

·难度

算法难度:B。

思维难度:A。

调码难度:A。

综合评价:普及/提高-。

·算法

宽度优先搜索。

·思路

先定义一个结构体,存储x、y坐标,重载加法运算为{a.x+b.x,a.y+b.y}。每一套关系都看做一条有权值的边,当然权值是“坐标”类型的,权值就是基准点(第一个数)的x、y分别加上多少(第3、4个数)能变为目标点(第二个数),当然反过来也要连接,只不过权值参数要变为“0-原来的数”。然后用bfs跑,入口就是1号小人在原点,每次遍历到另一个小人时就能求出该小人相应坐标,最后输出每个人的坐标,特判没有遍历到的点即可。

·代价

O(n+m),bfs占大头。

·细节

边的类型:vector<pair<Place,int>>edge[M]={};

队列的类型:pair<Place,int>q[N]={};

判段是否入队的数组的类型:bool pc[N]={};

·代码

#include
#define M 220000
#define N 220000
using namespace std;
struct Place{
    long long x,y;
    Place operator+(Place ot){
        return{x+ot.x,y+ot.y};
    }
};
vector>edge[M]={};
//边
pairq[N]={};
//队列
long long ansx[N]={},ansy[N]={},m=0,n=0;
//答案x坐标、答案y坐标、关系个数、人的个数
bool pc[N]={};
//判断是否在bfs中已经入队
int main(){
    scanf("%lld%lld",&n,&m);
    for(long long i=1;i<=m;i++){
        long long a=0,b=0;
        Place p={};
        scanf("%lld%lld%lld%lld",&a,&b,&p.x,&p.y);
        edge[a].push_back({p,b});
        Place q={-p.x,-p.y};
        edge[b].push_back({q,a});
    }
    //输入、连边
    long long front=1,rear=1;
    q[1]={{0,0},1};
    pc[1]=true;
    //原点入队
    while(front<=rear){
        for(pairi:edge[q[front].second]){
            if(pc[i.second]==false){
                rear++;
                q[rear]={q[front].first+i.first,i.second};
                //新元素入队
                ansx[i.second]=q[rear].first.x;
                ansy[i.second]=q[rear].first.y;
                //答案更新
                pc[i.second]=true;
                //标记入队
            }
        }
        front++;
        //队首出队
    }
    //bfs
    for(long long i=1;i<=n;i++){
        if(pc[i]==true){
            printf("%lld %lld\n",ansx[i],ansy[i]);
        }else{
            printf("undecidable\n");
        }
        //有入过队的输出坐标,否则输出“不知道”
    }
    //输出答案
    return 0;
}

·注意

反着连边的时候权值取反。

你可能感兴趣的:(开发语言,c++,bfs)