题目大意
有 n n n 个人,编号为 1 1 1 到 n n n 。
第 1 1 1 个人站在原点处,其余人的位置未知。
给定 m m m 条信息,第 i i i 条信息由四个参数 u , v , x , y u,v,x,y u,v,x,y 组成,表示第 v v v 个人相对于第 u u u 个人的横坐标增加了 x x x ,纵坐标增加了 y y y 。
现在请你求出所有人的坐标并输出。如果某个人的坐标求不出来,输出 undecidable
。
解题思路
建图,跑一边dfs即可。
对于给定的一条消息,如果第 v v v 个人相对于第 u u u 个人的横坐标增加了 x x x ,纵坐标增加了 y y y ,则同时也表示第 u u u 个人相对于第 v v v 个人的横坐标增加了 − x -x −x ,纵坐标增加了 − y -y −y 。于是建图时可以建双向关系。
G[u].push_back({v,x,y});
G[v].push_back({u,-x,-y});
然后跑一遍dfs,把能更新的人的坐标都更新即可(具体细节见代码)。
代码示例
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
struct node{
int u,x,y;
};
vector<node> G[200010];
int ansx[200010],ansy[200010];
//第i个人的横纵坐标
void dfs(int x){
for(int i=0;i<G[x].size();i++){
int v=G[x][i].u;
if(ansx[v]==0x3f3f3f3f3f3f3f3f){//如果他的坐标还是未知的
ansx[v]=ansx[x]+G[x][i].x;
ansy[v]=ansy[x]+G[x][i].y;
//这个人坐标已知后可以尝试去更新其他人
dfs(v);
}
}
}
signed main(){
memset(ansx,0x3f,sizeof(ansx));
memset(ansy,0x3f,sizeof(ansy));
//初始只有1号人站在原点
ansx[1]=ansy[1]=0;
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,x,y;
cin>>u>>v>>x>>y;
G[u].push_back({v,x,y});
G[v].push_back({u,-x,-y});
}
dfs(1);
for(int i=1;i<=n;i++){
if(ansx[i]!=0x3f3f3f3f3f3f3f3f) cout<<ansx[i]<<" "<<ansy[i]<<endl;
else cout<<"undecidable"<<endl;
}
return 0;
}