Codeforces 1635E Cars 题解
题目简述
一条数轴上有 \(n\) 辆车,每辆车都可以向左或向右定向移动,并且可以随时以任何恒定的正速度沿该方向移动。两辆车之间可以有以下两种关系:
-
如果两辆汽车无论速度如何都永远不会到达同一点,我们称它们为 无关紧要的。
-
如果两辆汽车无论速度如何,它们一定会到达同一点,我们称它们为 命中注定的。
现在给定 \(m\) 条关系,你要确定每辆车初始的位置与方向,满足这 \(m\) 条关系。
题目分析
首先,我们可以通过模拟发现如果两辆车是 无关紧要的,它们只能是相背而行。同理,如果两辆车是 命中注定的,它们则是相对而行。也就是说,无论给出那种关系,他们的方向必定是相反的,这启发我们使用二分图染色来确定他们的方向。
如果不是二分图,那必定无解。如果是,我们就让染成黑色的向左行驶,染成白色的向右行驶。当然,相反也是可以的。
接下来,我们考虑如何确定他们的位置,我们可以枚举每一对关系,为了方便一些,我们设 \(i\) 为向右行驶的车,\(j\) 为向左行驶的车。我们分成两种情况来讨论:
-
如果两辆车是 命中注定的,那么 \(i\) 一定在 \(j\) 的前方,读者可以画图模拟一下,这说明 \(i\) 的坐标 \(x_i\) 一定小于 \(j\) 的坐标 \(x_j\),即 \(x_i \lt x_j\)。
-
同理,如果两辆车是 无关紧要的,那么 \(j\) 一定在 \(i\) 的前方,这说明 \(x_j \lt x_i\)。
现在问题被转化成了给出 \(m\) 条形如 \(A \lt B\) 的关系,让你对其排序。我们可以利用 P1347 排序 的做法,分别建立一条 \(A \to B\) 的有向边,再进行拓扑排序,最后按出队顺序赋值即可,当然,如果图中有环的话就是无解。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,m,opt[N],x[N],y[N],col[N],tot,ans[N],in[N];
vector<int> G1[N],G2[N];
queue<int> q;
bool dfs(int u,int c)
{
col[u]=c;
for(int v:G1[u])
{
if(col[v]==c||(col[v]==-1&&!dfs(v,c^1))) return 0;
}
return 1;
}
bool topo()
{
for(int i=1;i<=n;i++)
{
if(!in[i]) q.push(i);
}
while(!q.empty())
{
int u=q.front();
q.pop();
ans[u]=tot++;
for(int v:G2[u])
{
if(!(--in[v]))
{
q.push(v);
}
}
}
return tot<n?1:0;
}
int main()
{
cin>>n>>m;
memset(col,-1,sizeof col);
for(int i=1;i<=m;i++)
{
cin>>opt[i]>>x[i]>>y[i];
G1[x[i]].push_back(y[i]);
G1[y[i]].push_back(x[i]);
}
for(int i=1;i<=n;i++)
{
if(col[i]==-1)
{
if(!dfs(i,0))
{
printf("NO\n");
return 0;
}
}
}
for(int i=1;i<=m;i++)
{
if(opt[i]==1)
{
if(col[x[i]]==1&&col[y[i]]==0)
{
G2[y[i]].push_back(x[i]);
in[x[i]]++;
}
else
{
G2[x[i]].push_back(y[i]);
in[y[i]]++;
}
}
else
{
if(col[x[i]]==1&&col[y[i]]==0)
{
G2[x[i]].push_back(y[i]);
in[y[i]]++;
}
else
{
G2[y[i]].push_back(x[i]);
in[x[i]]++;
}
}
}
if(topo())
{
printf("NO");
return 0;
}
printf("YES\n");
for(int i=1;i<=n;i++)
{
cout<<(!col[i]?'L':'R')<<" "<<ans[i]<<"\n";
}
return 0;
}

浙公网安备 33010602011771号